В моем коде есть сценарий, в котором я бы хотел, чтобы F # автоматически передавал значения одного типа функции (например, IBase -> unit
) другому, явно указанному типу функции (IDerived -> unit
). Хотя это, как представляется, в целом поддерживается, я обнаружил случаи, когда это не удалось без видимой причины.
В приведенном ниже коде case1
до case8
кажутся мне эквивалентными: в каждом случае с правой стороны есть выражение типа IBase -> unit
, которое связано с именем типа IDerived -> unit
. Так почему же не разрешены дела 4, 5 и 7?
type IBase = interface end
type IDerived = inherit IBase
let foo (x: IBase) = ()
let bar = fun (x: IBase) -> ()
type T = T with static member (!!) (_: T) = foo
let baz = !!T
let case1: IDerived -> unit = foo // OK
let case2: IDerived -> unit = bar // OK
let case3: IDerived -> unit = baz // OK
let case4: IDerived -> unit = !!T // Expecting 'IDerived -> unit' but given 'IBase -> unit'
let case5: IDerived -> unit = upcast !!T // Type 'IBase -> unit' is not compatible with type 'IDerived -> unit'
let case6: IDerived -> unit = let z = !!T in z // OK
let case7: IDerived -> unit = fun (x: IBase) -> () // Expected x to have type 'IDerived' but here has type 'IBase'
let case8: IDerived -> unit = let z = fun (x: IBase) -> () in z // OK
РЕДАКТИРОВАТЬ: Чтобы уточнить, я в основном задаюсь вопросом, почему компилятор не рассматривает 8 случаев одинаково. Например, я ожидал бы, что привязка let z...
в case8
будет излишней, но все же она имеет значение (по сравнению с case7
). Почему?
РЕДАКТИРОВАТЬ: Вот код для демонстрации того, чего я пытаюсь достичь: https://dotnetfiddle.net/AlpdpO Он также содержит решение / обходной путь, поэтому я действительно спрашиваю больше о технических деталях / причинах, а не об альтернативных подходах. Я уже думал о том, чтобы поднять проблему с GitHub, но чувствую, что проблема, скорее всего, просто недоразумение с моей стороны.