我正在尝试在 FSharp 中创建一个函数,该函数将采用接口(interface)类型的参数和派生类型的参数,并将这两个参数作为该接口(interface)的实现传递:
简化示例:
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)上遇到以下两个错误:
关于参数:
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 上找到。
最佳答案
#
是子类型约束的语法糖,即。 comp2
相当于:
let comp2<'T, 'U when 'U :> 'T> (x:'T) (y:'U) = doCompare x (y :> 'T)
不幸的是,类型系统不支持 'U :> 'T
部分(您不能将类型约束为类型变量的子类型),因此这是不可能的。
关于f# - 涉及静态类型转换的 f# 方法的泛型类型约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22144571/