简体   繁体   English

F#中重载的内联运算符:(| + |)

[英]Overloaded inline operators in F#: ( |+| )

I'm trying to define an overloaded operator, eg |+| 我正在尝试定义一个重载的运算符,例如|+| , as the following: ,如下:

let inline ( |+| ) (m1 : #IMeasurable) (m2 : #IMeasurable) = m1.Measure + m2.Measure

The problem is, I can't do something like: 问题是,我做不了类似的事情:

let three = m1 |+| m2 |+| m3

Because the operator |+| 因为运算符|+| isn't defined for the case (m1 : int) (m2 : #IMeasurable) . 没有为案例定义(m1 : int) (m2 : #IMeasurable) Is there a way to overload this operator or use static type constraints to make the above expression possible? 有没有办法重载此运算符或使用静态类型约束使上述表达式成为可能? Is there a way to modify IMeasurable (which I can edit) so that this is possible? 有没有办法修改IMeasurable (我可以编辑),这是可能的? Anything else that would allow the above expression to work? 还有什么能让上面的表达能够起作用?

Thank you. 谢谢。

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

Not tested, since I don't have IMeasurable, but it may do the job. 没有经过测试,因为我没有IMeasurable,但它可以完成这项工作。

If you're defining an operator that behaves like + then I think the best design is to define an operator that returns a value of the same type as is the type of its arguments. 如果你正在定义一个行为类似于+的运算符,那么我认为最好的设计是定义一个运算符,它返回与其参数类型相同类型的值。 This means that I would change the operator to return IMeasurable instead of int : 这意味着我将更改运算符以返回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)

This will make the operator definition more uniform and easier to use. 这将使操作员定义更加统一和易于使用。 The code you wanted to write will now work (returning IMeasurable ), but you can also use Seq.reduce : 您想要编写的代码现在可以工作(返回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 (|+|)

That said, if you really want to overload an operator that is defined using let and you cannot add it to a type as static member (because you cannot modify the type), then you'll need to use the trick that Gustavo describes 也就是说,如果你真的想要重载使用let定义的运算符,你不能将它作为静态成员添加到类型中(因为你不能修改类型),那么你需要使用Gustavo描述的技巧

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM