如何强制类型签名

How to enforce type signature

在下面的代码中,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

如何解决是比较容易的部分,使 findq0 成为 通用函数:

let findq0 x = queue_it _find x // int -> 'a

与你所拥有的不同之处在于你的版本

let findq0 = queue_it _find    // int -> User

findq0 是一个 通用值 ,这是 .Net 的一个问题,通常会导致这样的错误消息

Value restriction. The value 'findq0' has been inferred to have generic type val findq0 : (int -> '_a) when '_a :> Answer.foo.MBase Either make the arguments to 'findq0' explicit or, if you do not intend for it to be generic, add a type annotation.

如果您注释掉代码的最后两行,您可以看到该消息。 F# 尝试根据您对 findq0 的首次使用猜测一个非泛型值来避免出现该消息,即:

    let u3 : User  = findq0 42

这一行告诉 F# findq0 应该 return 类型 User 的值,因此它确定它应该是 int -> User 类型。下一行与它相矛盾,因此您会收到一条错误消息:

This expression was expected to have type 'User2' but here has type 'User'