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
这样的东西并不太长,也不容易编写和理解。