#inheritance #f#
#f# #тип модуля
Вопрос:
Кто-нибудь знает, почему это не удается скомпилировать?
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:
Это выглядит как неприятный угловой случай в языке F #, но я не уверен, квалифицируется ли это как ограничение по дизайну или ошибка в компиляторе. Если это связано с ограничением конструкции, то в сообщении об ошибке должно быть указано это (потому что в настоящее время это не имеет особого смысла).
В любом случае, проблема в том, что компилятор F # не генерирует код, который на самом деле содержит unit
тип в IL. Он заменяет его на void
(при использовании в качестве возвращаемого типа) или на пустой список аргументов (при использовании в качестве аргумента метода или функции).
Это означает, что в MyClass
типе компилятор решает скомпилировать MyFun
элемент как метод, который принимает string
и возвращает void
(но вы не можете использовать void
в качестве аргумента универсального типа, поэтому это просто не работает). В принципе, компилятор мог бы использовать фактический unit
тип в этом случае (потому что это единственный способ заставить его работать), но это, вероятно, создало бы другие несоответствия в другом месте.
Я думаю, что ваш трюк с созданием MyUnit
— это прекрасный способ решить проблему. Даже базовая библиотека F # использует что-то подобное MyUnit
в некоторых местах реализации (в асинхронных рабочих процессах), чтобы справиться с некоторыми ограничениями unit
(и способом ее компиляции).
Комментарии:
1. Спасибо, Томас. Я не видел этой проблемы где-либо еще (например, в обычных функциях с let;)
2. @Stefan: Если вы используете
unit
тип в качестве аргумента (для функции или типа), то это, как правило, нормально. Эта ошибка / ограничение, вероятно, появляется только при реализации абстрактных элементов (что является немного сложной областью для компилятора F #, поскольку наследование в .NET удивительно сложное)3. Интересно, что это будет работать на C #, и я могу использовать функцию на F #. Вероятно, следует сообщить об ошибке.