如何执行类型签名

时间:2018-10-21 22:07:54

标签: generics f# type-inference

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

1 个答案:

答案 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”,但此处具有类型       “用户”