Почему F # выдает этот тип?
Это мой код:
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 говорит мне, что тип 'a был ограничен' t из-за выражения (f v')
в c.set (f v')
. Является ли проблема, что новая ячейка вынуждена иметь тип Cell <t> , потому что мы находимся в определении класса?
Я уверен, что проблема в том, что если я определяю карту как отдельную функцию, то 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>
Я хотел бы использовать элемент, но этот менее общий тип делает мой тип ячейки бесполезным... Как решить эту проблему?
Спасибо!
Jules
Ответы
Ответ 1
У меня нет коробки с Beta1 под рукой прямо сейчас (в наших внутренних битах это теперь, кажется, выводит правильный тип, поэтому, надеюсь, это означает, что это будет исправлено в Beta2).
Я ожидаю, что вы можете указать подпись полного типа:
member x.map<'a> (f:'t -> 'a) : Cell<'a> =
и он будет работать.
UPDATE
Я попробовал на Beta1, и на самом деле "fix" есть
member x.set (v':'t) : unit =
Непонятно, почему добавление этой сигнатуры типа помогает.