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

mar*_*lam 2 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)
Run Code Online (Sandbox Code Playgroud)

我在泛型版本上遇到以下两个错误(这里是comp2):

在参数上:

This construct causes code to be less generic than indicated by its type annotations. 
The type variable implied by the use of a '#', '_' or other type annotation at or near '...' 
has been constrained to be type ''T'.

在演员操作员:

The static coercion from type 'T to 'T involves an indeterminate type based on information prior to this program point. 
Static coercions are not allowed on some types. Further type annotations are needed.

有没有办法解决这个问题,除了使用'T'U创建签名并通过对象进行投射显然不安全?

这段代码(连同显示此问题的原始代码 - 用于将NSubstitute包装在测试夹具中)可在tryfsharp找到

Tar*_*mil 5

#是一个亚型的约束,即语法糖.comp2相当于:

let comp2<'T, 'U when 'U :> 'T> (x:'T) (y:'U) = doCompare x (y :> 'T)
Run Code Online (Sandbox Code Playgroud)

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