Overloaded inline operators in F#: ( |+| )

前端 未结 2 1639
感情败类
感情败类 2020-12-04 02:51

I\'m trying to define an overloaded operator, e.g. |+|, as the following:

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


        
相关标签:
2条回答
  • 2020-12-04 03:13

    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:

    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:

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

    0 讨论(0)
  • 2020-12-04 03:26
    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.

    0 讨论(0)
提交回复
热议问题