在下面的代码中,queue_it
以一种意想不到的方式更改了类型签名。我该如何解决?
module foo =
type MBase() =
member __.id = 42
type User() = inherit MBase()
type User2() = inherit MBase()
let queue_it f = fun x -> f x
let _find(x:int) = (Unchecked.defaultof<#MBase>)
let find0 = fun x -> _find x // int -> #MBase
let findq0 = queue_it _find // int -> MBase ??
let u1 : User = find0 42
let u2 : User2 = find0 42
let u3 : User = findq0 42
let u4 : User2 = findq0 42 // error: Expected User2 but given User
答案 0 :(得分:2)
解决方法很容易,将findq0
设为通用函数:
let findq0 x = queue_it _find x // int -> 'a
与您所拥有的版本不同之处在于
let findq0 = queue_it _find // int -> User
findq0
是通用值,这是.Net的问题,通常会导致这样的错误消息
值限制。值“ findq0”已推断为具有 通用类型 val findq0:(int->'_a)当'_a:> Answer.foo.MBase时,请明确指定'findq0'的参数,或者如果您不打算使用 要通用,请添加类型注释。
如果您注释掉代码的最后两行,则可以看到该消息。 F#会根据您对findq0
的首次使用来猜测一个非通用值,从而避免出现该消息:
let u3 : User = findq0 42
此行告诉F#findq0
应该返回类型User
的值,因此它确定它应该是int -> User
类型的值。下一行与之矛盾,因此您会看到一条错误消息:
该表达式应具有类型 “ User2”,但此处具有类型 “用户”