【问题标题】:Generic type constrained on f# method involving static type conversion泛型类型受限于涉及静态类型转换的 f# 方法
【发布时间】:2014-03-03 10:42:09
【问题描述】:

我正在尝试在 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 上获得

【问题讨论】:

    标签: f#


    【解决方案1】:

    # 是子类型约束的语法糖,即。 comp2 相当于:

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

    很遗憾,类型系统不支持'U :&gt; 'T 部分(您不能将类型约束为类型变量的子类型),因此这是不可能的。

    【讨论】:

    • 感谢您的解释。从那个解释(不包括在错误消息中:-)我找到了这个引用语言规范的答案:stackoverflow.com/a/3857528/59371
    • 在处理子类型约束时,请始终牢记以下几点:您确定需要将 'T 的子类型作为参数,还是仅使用 'T 就足够了?在许多情况下,函数参数会根据需要自动向上转换,从而使子类型约束变得多余。
    猜你喜欢
    • 2012-02-10
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 2011-02-18
    • 2011-03-23
    • 1970-01-01
    • 2018-02-21
    • 2015-03-09
    相关资源
    最近更新 更多