FSharp和上行转换到接口似乎是多余的



我有以下使用响应式扩展的代码片段:

    let value : 't = ...
    Observable.Create<'t>(fun observer ->
        let subject = new BehaviorSubject<'t>(value)
        let d0 = subject.Subscribe(observer)
        let d1 = observable.Subscribe(subject)
        new CompositeDisposable(d0, d1) :> IDisposable
    )

这工作。但是,如果我将向上转换为IDisposable,那么代码就会失败编译时,引用模棱两可的重载。然而,CompositeDisposable是一个IDisposable。为什么类型推断引擎无法解决此问题?注意,我在c#中几乎一直使用这个模式,从Observable返回CompositeDisposable。

正如@kvb所说,函数不支持方差,所以接口和子类需要向上转换。

下面是一个演示子类行为的小示例:
type A() =
    member x.A = "A"
    
type B() =
    inherit A()
    member x.B = "B"
let f (g: _ -> A) = g()
let a = f (fun () -> A()) // works
let b = f (fun () -> B()) // fails

如果函数f是由你编写的,添加类型约束可能会有所帮助:

// This works for interface as well
let f (g: _ -> #A) = g()
let a = f (fun () -> A()) // works
let b = f (fun () -> B()) // works

否则,你必须做一点向上转换,正如你的例子所描述的。

编辑:从f# 6.0开始,接口和子类的自动转换现在默认支持。

最新更新