Reputation: 6346
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
Upvotes: 1
Views: 501
Reputation: 118865
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.
Upvotes: 2