Краткое описание проблемы
В момент, когда используется f #, я должен явно привести значение к родительскому типу его типа, чтобы получить правильные выражения соответствия шаблонов для проверки типа.В идеале я бы хотел более аккуратный способ сделать это.
Пример
Предположим, у меня есть некоторая иерархия классов:
type Foo () =
abstract member Value : unit -> string
type A (i:int) =
inherit Foo ()
override this.Value () = i.ToString()
type B (s:string) =
inherit Foo ()
override this.Value () = s
В идеале и в некоторыхна языках программирования в обычном режиме я бы написал эквивалент следующего:
let bar (i:int) : Foo =
match i with
| 1 -> B "one"
| _ -> A i
Однако это не дает возможности правильно проверить тип, выдавая ошибку: «Ожидалось, что это выражение будет иметь тип Foo, но здесь имеет тип B».Я не понимаю, почему у компилятора недостаточно информации, чтобы вывести общий супертип для выражения соответствия, а затем проверить, что общим супертипом является 'Foo'.
В настоящее время я вынужден предоставитьявное принуждение для каждого случая в сопоставлении с образцом:
let bar2 (i:int) : Foo =
match i with
| 1 -> (B "one") :> Foo
| _ -> (A i) :> Foo
Я бы хотел избежать этого.
Дополнительные примечания
- Интуиция предполагает, что это является результатом более общей проблемы.Хотя я бы подумал, что что-то такое же общее, как сопоставление с образцом, или если операторы, которые также демонстрируют то же свойство, будут иметь правило проверки типа для учета общих супертипов.
- Прежде чем кто-либо предложит - я ценю, что еслиA или B были бы объектными выражениями, это работало бы, но мой реальный пример - создание экземпляров классов C #, где они являются обычными классами.
- Есть ли способ для меня объявить функции для неявного преобразования типов, как, например, scalaимеет, так что я могу применить автоматические преобразования для модуля, где я делаю это поколение?
Спасибо за любую помощь по этому вопросу.