F# 运算符重载之谜

标签 f# operator-overloading

在 F# 中,运算符重载似乎很强大,但要正确实现也很棘手。 我有以下类(class):

 type Value<'T> = 
    with
        static member inline  (+) (a : Value<'U>, b: Value<'U>) : Value<'U> = 
           do stuff

如果我为 + 定义另一个重载:

static member inline  (+) (a : Value<'U>, b: 'U) : Value<'U> = 
           do stuff

它有效。但如果我想要一个对称运算符:

static member inline  (+) (b: 'U, a : Value<'U>) : Value<'U> = 
           do stuff

编译器提示:

let a = Value<int>(2);
let b = a + 3 // ok
let c = 3 + a //<-- error here

错误 3 类型推理问题过于复杂(已达到最大迭代深度)。考虑添加更多类型注释

有没有办法解决这个问题并保持通用?

我使用的是 F# 3.1

谢谢

最佳答案

编译器永远没有选择:当您应用(+)时运算符,您可以给它一些类型 int或类似的东西Value<'U> 。某种类型的东西int不能被视为 Value<'U> 类型,反之亦然。

让我们在解释器中尝试一下。我将两个实现输出 A 和 B,这样我们就可以知道哪个被调用了:

> type Value<'T> = 
-       { a : 'T  }
-     with
-         static member inline (+) (a : Value<'U>, b: Value<'U>) : Value<'U> = 
-            printfn "A"; a
-         static member inline (+) (a : Value<'U>, b: int) : Value<'U> = 
-            printfn "B"; a
- ;;

type Value<'T> =
  {a: 'T;}
  with
    static member ( + ) : a:Value<'U> * b:Value<'U> -> Value<'U>
    static member ( + ) : a:Value<'U> * b:int -> Value<'U>
  end

现在我们有了一个类型。让我们来评估一下它的值(value)。

> let t = { a = "foo" };;

val t : Value<string> = {a = "foo";}

我们现在可以尝试重载。第一 int :

> t + 4;;
B
val it : Value<string> = {a = "foo";}

好的。现在Value<string> :

> t + t;;
A
val it : Value<string> = {a = "foo";}

关于F# 运算符重载之谜,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22365367/

相关文章:

c++ - 如何编写带有自定义标志的 ostream 运算符

c++ - std::ios_base::ios_base(const std::ios_base) 是私有(private)的

f# - fslex - 如何在两个 token 集之间切换?

f# - 函数的名称,如 Option.bind,当输入为 None 时返回 Some(x)

unit-testing - 具有副作用的 F# UnitTesting 函数

c++ - 为什么存储在 STL 容器中的类禁止重载 operator&()?

F# 向上转换基础

.net - MSBuild 和 F# 的 FAKE 有什么区别?

c++ - 如何重载 operator[] 以允许 `object[a] = b` ?

c++ - 没有typedef返回成员函数指针的语法是什么?