Why does F# infer this type?

妖精的绣舞 提交于 2019-12-13 00:20:16

问题


This is my code:

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

My problem is with the map member. F# infers the type

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

I think it should infer this more general type (just like Seq's map):

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

And in fact if I declare the type like that, Visual Studio tells me that the type 'a has been constrained to 't because of the expression (f v') in c.set (f v'). Is the problem that the new Cell is forced to have type Cell<'t> because we're in the class definition?

I'm pretty sure that's the problem because if I define map as a separate function then F# does infer the type I want:

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

Namely

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

I would like to use a member, but this less general type makes my Cell type useless... How do I solve this problem?

Thanks! Jules


回答1:


I don't have a box with Beta1 handy right now (in our internal bits this now seems to infer the correct type, so hopefully that means this will be fixed in Beta2).

I expect you can specify a full type signature:

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

and it will work.

UPDATE

I tried on Beta1, and in fact the 'fix' is

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

I am unclear why adding this type signature helps.



来源:https://stackoverflow.com/questions/1134647/why-does-f-infer-this-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!