generics - F# 类型参数缺少约束

标签 generics f# type-constraints type-parameter

我正在尝试为包装类定义通用加法运算符。到目前为止我有这个:(从实际代码简化)

type Wrap<'a> =
    | Wrap of 'a
    static member inline (+) (Wrap x, Wrap y) = Wrap (x + y)

let inline addSelf x = x + x

确实有效:

let i = addSelf (Wrap 1)  // returns Wrap 2
let f = addSelf (Wrap 1.) // returns Wrap 2.0

但是以下 addSelf 的替代方案无法编译

let inline addSelf'  (Wrap x) = (Wrap x) + (Wrap x) // compile error

给出错误 FS0193:类型参数缺少约束 'when (^a 或 ^?15169) : (static member (+) : ^a * ^?15169 -> ^?15170)'

为什么当 addSelf 工作正常时,更受限制的 addSelf' 却不起作用?谢谢!

最佳答案

正如我在评论中所说,我认为这是一个错误。这是我的推理。当编译器看到

let inline addSelf (Wrap x) = (Wrap x) + (Wrap x)

我认为大致应该做出以下推论:

  1. 参数的类型为 Wrap< ^t>一些新鲜的^t .
  2. 因此x类型为^t .
  3. 因此,右侧的操作数也都是 Wrap< ^t> 类型.
  4. 这些值将被传递到 (+)运算符(operator)。因此,Wrap< ^t>需要支持静态运算符 (+)类型 Wrap< ^t> * Wrap< ^t> -> ^u对于一些新鲜类型^u .
  5. 唯一的静态运算符 (+)定义于Wrap<_>类型为Wrap< ^a> * Wrap< ^b> -> Wrap< ^c> when (^a or ^b) : (static member (+) : ^a * ^b -> ^c .
  6. 统一类型变量,整体类型addSelf应该是addSelf : Wrap< ^t> -> Wrap< ^c> when ^t : (static member (+) : ^t * ^t -> ^c)

各种类型推断步骤都很棘手,所以我肯定可能遗漏了一些东西,而这种行为是预期的。另一方面,各种类型推断步骤很棘手,因此它们有点错误:)。还令人担忧的是,您无法注释函数和所有子表达式并编译代码:

let inline doStuff< ^t, ^u when ^t : (static member (+) : ^t * ^t -> ^u)> ((Wrap x) : Wrap< ^t>) : Wrap< ^u> =
    ((Wrap x) : Wrap< ^t>) + ((Wrap x) : Wrap< ^t>)

您仍然会收到编译器错误,其中包含对新类型参数的神秘引用 ^?12020^?12021 (或者你的情况下任何独特的整数)。我认为这不应该发生。

关于generics - F# 类型参数缺少约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6849557/

相关文章:

具有泛型的 C# 语法

java - 使用 GSON 反序列化的父对象的参数实例化子对象并使用泛型?

java - 为什么这段带有泛型的java代码不能编译

f# - System.MissingMethodException : Method not found: 'FSharp. Data.HttpResponse

haskell - Data.Map中键/值关系的静态保证

reactjs - 键入 React 组件工厂函数

java - 通用二叉搜索树 Java 类型参数不在范围内

f# - FsUnit 和检查 float 的相等性

C# 和 F# - 什么情况下需要一个或另一个

Scala:由嵌套类型值参数化的类型级编程