代码之家  ›  专栏  ›  技术社区  ›  Ray

如何强制类型签名

  •  1
  • Ray  · 技术社区  · 7 年前

    在下面的代码中, 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 回复  |  直到 7 年前
        1
  •  2
  •   AMieres    7 年前

    如何解决是最容易的部分,使 findq0 通用函数 :

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

    与你的版本不同的是

    let findq0 = queue_it _find    // int -> User
    

    FUNQ0 是一个 一般价值 ,这是.NET的一个问题,通常会导致这样的错误消息

    价值限制。已推断值“findq0”具有 泛型类型 val findq0:(int->'_a)当'_a:>answer.foo.mbase将参数设置为“findq0”显式,或者,如果您不打算 它是通用的,添加一个类型注释。

    如果对代码的最后两行进行注释,则可以看到该消息。f根据第一次使用 FUNQ0 这是:

        let u3 : User  = findq0 42
    

    这一行告诉F FUNQ0 应返回类型的值 User 所以它决定了它应该是 int -> User . 下一行与之相反,因此您会得到一个错误,即:

    此表达式应具有类型 “user2”,但这里有类型 “用户”