Как неявно преобразовать в общие супертипы в совпадениях с образцом F #?
Краткое описание проблемы
В тот момент, когда используется 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, чтобы я мог применить автоматические преобразования для модуля, где я делаю это поколение?Спасибо за любую помощь в этом вопросе.