Ошибка наследования интерфейса F # из-за единицы - PullRequest
17 голосов
/ 20 декабря 2010

Кто-нибудь знает, почему это не скомпилируется?

type MyInterface<'input, 'output> = 
    abstract member MyFun: 'input -> 'output

type MyClass() = 
    interface MyInterface<string, unit> with
        member this.MyFun(input: string) = ()
    //fails with error FS0017: The member 'MyFun : string -> unit' does not have the correct type to override the corresponding abstract method.
type MyUnit = MyUnit
type MyClass2() = 
    //success
    interface MyInterface<string, MyUnit> with
        member this.MyFun(input: string) = MyUnit

1 Ответ

17 голосов
/ 20 декабря 2010

Это похоже на неприятный угловой случай в языке F #, но я не уверен, квалифицируется ли это как ограничение по конструкции или как ошибка в компиляторе.Если это ограничение конструкции, то в сообщении об ошибке должно быть сказано (потому что в настоящее время это не имеет особого смысла).

В любом случае, проблема в том, что компилятор F # не генерирует код, который на самом деле содержиттип unit в IL.Он заменяет его на void (при использовании в качестве возвращаемого типа) или на пустой список аргументов (при использовании в качестве аргумента метода или функции).

Это означает, что в типе MyClass компилятор решает скомпилировать элемент MyFun как метод, который принимает string и возвращает void (но вы не можете использовать void в качестве универсальноговведите аргумент, так что это просто не работает).В принципе, компилятор может использовать фактический тип unit в этом случае (потому что это единственный способ заставить его работать), но это, вероятно, приведет к другим несоответствиям в других местах.

Ваш трюк с созданием MyUnitЯ думаю, это прекрасный способ решения проблемы.Даже базовая библиотека F # использует что-то вроде MyUnit в некоторых местах реализации (в асинхронных рабочих процессах), чтобы справиться с некоторыми ограничениями unit (и способом его компиляции).

...