фон:F # вложенных обобщенные типов, не совместимые с реализованным типом
Учитывая следующие два заявления в качестве F # программы:
- типа
A
реализует интерфейсWrapped<int>
- типа
B
реализует интерфейсWrapped<A>
Мы говорим, что тип A
совместим с Wrapped<int>
и тип B
совместим с Wrapped<A>
- совместим, насколько мне известно, что означает, что A
можно передать в функцию, требующую Wrapped<int>
.
Проблема:
Из моего опыта с программированием, я ожидал бы следующее быть правдой, учитывая приведенные выше два заявления:
- типа
B
должен быть совместим с типомWrapped<Wrapped<int>>
с B
имеет A
как параметр типа, где Wrapped<int>
должен идти, и A
и Wrapped<int>
совместимы.
Это не тот случай. Следующая реализация:
type Wrapper<'a> = abstract member Value : 'a
type A =
| A of int
interface Wrapper<int> with member this.Value = (let (A num) = this in num)
type B =
| B of A
interface Wrapper<A> with member this.Value = (let (B a) = this in a)
let f (x:Wrapper<Wrapper<int>>) =
x.Value.Value
let testValue = f (B (A 1))
имеет ошибку компиляции на B (A 1)
о том,
Тип
B
не совместим с типомWrapper<Wrapper<int>>
Вопрос:
Так как я смог логически сделать Является ли я что-то не так, выполняя это? Или F # не имеет этой функции «вложенной совместимости», и если это так, есть ли особая причина для ее отсутствия?
Существует обходной путь к этому:
type B =
| B of A
interface Wrapper<Wrapper<int>> with member this.Value = (let (B a) = this in a :> Wrapper<int>)
Это позволит устранить ошибку компиляции, хотя он чувствует себя немного не так. Я спрашиваю себя: «А что, если я когда-нибудь написать функцию для работы на Wrapper<A>
типов? (Если я когда-либо добавить больше Wrapper<A>
внедренцев)
Ваши предположения неверны: в F # нет автоматического подтипирования (т. Е. Вы обычно не можете передавать подтип функции, ожидающей супертипа, если вы специально не объявляете эту функцию), и не всегда верно, что ' T:?> T 'когда' X:?> Y'. Это свойство называется «ковариация» (google it), и это не всегда выполняется. –