在涉及静态类型转换的f#方法上约束的泛型类型



我正试图在FSharp中创建一个函数,该函数将接受一个接口类型的参数和一个派生类型的参数,并将这两个参数作为该接口的实现传递:

简化示例:

type IFoo =
abstract member Compare : IFoo -> bool
type Foo =
interface IFoo with
member this.Compare _ = false
let doCompare (a : IFoo) (b : IFoo) = a.Compare(b)
let comp  (x : IFoo) (y : #IFoo) = doCompare x (y :> IFoo)
let comp2 (x : 'T)   (y : #'T)   = doCompare x (y :> 'T)

我在通用版本(这里是comp2)上得到了以下两个错误:

关于参数:

此构造导致代码不像其类型注释所指示的那样具有泛型。在"…"处或附近使用"#"、"_"或其他类型批注所隐含的类型变量已被限制为类型"T">

在铸造操作员:

从类型"T"到"T"的静态强制涉及基于此程序点之前的信息的不确定类型。某些类型不允许使用静态强制。需要进一步的类型注释

除了使用'T'U创建签名并通过对象进行强制转换(这显然是不安全的)之外,有没有其他方法可以解决这个问题?

此代码(以及显示此问题的原始代码-用于将NSubstitute包装在测试夹具中)可在tryfsharp 上获得

#是子类型约束的语法糖,即comp2等价于:

let comp2<'T, 'U when 'U :> 'T> (x:'T) (y:'U) = doCompare x (y :> 'T)

不幸的是,类型系统不支持'U :> 'T部分(不能将类型约束为类型变量的子类型),因此这是不可能的。

最新更新