为什么编译:
let (|T|F|) b =
let f (o:int) : obj = null
if b then T else F(f)
Run Code Online (Sandbox Code Playgroud)
虽然失败了:
let (|T|F|) b =
let f (o:obj) : obj = null
if b then T else F(f)
Run Code Online (Sandbox Code Playgroud)
两个例子之间的区别是参数'o'被强制为'int'(编译)或'obj'(编译失败)
这是一个不幸的类型推理角案例.这将有效:
let (|T|F|) b : Choice<unit,obj -> obj> =
let f (o:obj) : obj = null
if b then T else F(f)
Run Code Online (Sandbox Code Playgroud)
在原始代码中,尽管有注释(o:obj),但F#推断o实际上可以是任何类型'a,这会导致类型的通用活动模式bool -> Choice<unit,'a -> obj>.因为'a是自由类型变量,F#将不接受此活动模式定义.如果您执行以下操作,您可以看到类似的问题:
let (|T|F|) b =
if b then T else F []
Run Code Online (Sandbox Code Playgroud)
同样,解决方案是将定义单一化:
let (|T|F|) b : Choice<unit,int list> =
if b then T else F []
Run Code Online (Sandbox Code Playgroud)