在 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/