Syntax F#:(|和#x2B;|)中的重载内联运算符

Syntax F#:(|和#x2B;|)中的重载内联运算符,syntax,f#,operator-overloading,Syntax,F#,Operator Overloading,我试图定义一个重载运算符,例如|+|,如下所示: let inline ( |+| ) (m1 : #IMeasurable) (m2 : #IMeasurable) = m1.Measure + m2.Measure 问题是,我不能这样做: let three = m1 |+| m2 |+| m3 因为操作符|+|没有为案例(m1:int)(m2:imeasuable)定义。是否有方法重载此运算符或使用静态类型约束使上述表达式成为可能?有没有办法修改IMeasurable(我可以编辑)使之

我试图定义一个重载运算符,例如
|+|
,如下所示:

let inline ( |+| ) (m1 : #IMeasurable) (m2 : #IMeasurable) = m1.Measure + m2.Measure
问题是,我不能这样做:

let three = m1 |+| m2 |+| m3
因为操作符
|+|
没有为案例
(m1:int)(m2:imeasuable)
定义。是否有方法重载此运算符或使用静态类型约束使上述表达式成为可能?有没有办法修改
IMeasurable
(我可以编辑)使之成为可能?还有什么能让上述表达式起作用的吗

多谢各位

type Overloads = Overloads with
    static member ($) (Overloads, m1: #IMeasurable) = fun (m2: #IMeasurable) -> m1.Measure + m2.Measure 
    static member ($) (Overloads, m1: int) = fun (m2: #IMeasurable) -> m1 + m2.Measure

let inline ( |+| ) m1 m2 = (Overloads $ m1) m2

未测试,因为我没有IMeasurable,但它可以完成这项工作。

如果要定义一个行为类似于
+
的运算符,那么我认为最好的设计是定义一个返回与其参数类型相同类型的值的运算符。这意味着我会将运算符更改为返回
IMeasurable
,而不是
int

type IMeasurable =
  abstract Measure : int

let newMeasure m = 
  { new IMeasurable with 
      member x.Measure = m }

let inline ( |+| ) (m1 : #IMeasurable) (m2 : #IMeasurable) = 
  newMeasure (m1.Measure + m2.Measure)
这将使操作符定义更加统一和易于使用。您想要编写的代码现在可以工作了(返回
IMeasurable
),但您也可以使用
Seq.reduce

// Now you can add multiple measure values without issues
let res = (newMeasure 2) |+| (newMeasure 3) |+| (newMeasure 4)

// Moreover, you can also use `Seq.reduce` which would not work
// with your original operator (because it has wrong type)
let res = [newMeasure 2; newMeasure 3; newMeasure 4] |> Seq.reduce (|+|)

也就是说,如果你真的想重载一个使用
let
定义的操作符,并且你不能将它作为静态成员添加到类型中(因为你不能修改该类型),那么你需要使用Gustavo描述的技巧,在这种情况下,返回
IMeasurable
恐怕没有意义。嗯,如果返回
IMeasurabe
没有逻辑意义,那么您可能需要遵循@Gustavo的建议。虽然这可能意味着使用一个简单的函数,将
IMeasurable
转换为
int
,然后对
int
使用标准
+
,这将是一个很好的选择。自定义操作符很难发现,而像
m1.Measure+m2.Measure+m3.Measure
这样的东西并不太长,也不容易编写和理解。