为什么F#推断这种类型?

时间:2009-07-15 23:28:36

标签: .net f# types type-inference

这是我的代码:

type Cell<'t>(initial : 't) =
    let mutable v = initial
    let callbacks = new List<'t -> unit>()
    member x.register c = callbacks.Add(c)
    member x.get () = v
    member x.set v' = 
        if v' <> v 
        then v <- v'
             for callback in callbacks do callback v'
    member x.map f = 
        let c = new Cell<_>(f v)
        x.register(fun v' -> c.set (f v')) ; c

我的问题在于map成员。 F#推断出类型

map : ('t -> 't) -> Cell<'t>

我认为它应该推断出这种更通用的类型(就像Seq的地图一样):

map : ('t -> 'a) -> Cell<'a>

事实上,如果我声明类似的类型,Visual Studio会告诉我,由于(f v')中的表达式c.set (f v'),类型'a'已被约束为't}。问题是新Cell被迫具有类型Cell&lt; t&gt;因为我们在课堂定义中?

我很确定这是问题所在,因为如果我将map定义为一个单独的函数,那么F#会推断出我想要的类型:

let map f (c : Cell<_>) = 
    let c' = new Cell<_>(f (c.get ()))
    c.register(fun v' -> c'.set (f v')) ; c' 

map : ('a -> 'b) -> Cell<'a> -> Cell<'b>

我想使用一个成员,但这种不太通用的类型使我的Cell类型无用......我该如何解决这个问题?

谢谢! 朱

1 个答案:

答案 0 :(得分:2)

我现在没有方便使用Beta1的方框(在我们的内部位中,现在似乎推断出正确的类型,所以希望这意味着这将在Beta2中修复)。

我希望您可以指定完整类型签名:

    member x.map<'a> (f:'t -> 'a) : Cell<'a> = 

它会起作用。

<强>更新

我试过Beta1,实际上'修复'是

member x.set (v':'t) : unit = 

我不清楚为什么添加此类签名会有所帮助。