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