Почему 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>

Я хотел бы использовать член, но этот менее общий тип делает мой тип Cell бесполезным... Как мне решить эту проблему?

Спасибо! Жюль

1 ответ

Решение

У меня нет коробки с бета-версией прямо сейчас (в наших внутренних битах это, кажется, выводит правильный тип, так что, надеюсь, это означает, что это будет исправлено в бета-версии 2).

Я ожидаю, что вы можете указать полную подпись типа:

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

и это будет работать.

ОБНОВИТЬ

Я пробовал на Beta1, и на самом деле "исправить"

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

Мне неясно, почему добавление этой подписи типа помогает.

Другие вопросы по тегам