在F#中,是否可以为元组实现运算符?

时间:2019-01-06 13:51:15

标签: f#

我正在使用一个表示float * float之类的点的API。

这些不方便对以下内容进行算术运算:

let a = (3.0, 4.0)
let b = (2.0, 1.0)

let c = (fst a + fst b, snd a + snd b)

我想写:

let c = a + b

如果我定义自己的类型,我可以这样做:

type Vector2 =
  {
    X : float;
    Y : float;
  }
  with
    static member (+) (a : Vector2, b : Vector2) =
      { X = a.X + b.X; Y = a.Y + b.Y }

但是随后我需要转换为我正在使用的API:

let c = a + b
let cAsTuple = (c.X, c.Y)

或者,我可以创建一个自由函数:

let add (ax, ay) (bx, by) = 
  (ax + bx, ay + by)

let c = a |> add b

但这并不像真正的中缀运算符那么好。

F#是否允许我为元组定义自定义运算符?

2 个答案:

答案 0 :(得分:7)

如果您愿意使用(+.)之类的其他运算符,则可以执行以下操作:

let inline (+.) (a,b) (c,d) = (a + c, b + d)

它适用于整数,浮点数和字符串:

( 4 ,  3 ) +. ( 3 ,  2 ) // (7, 5)
( 4.,  3.) +. ( 3.,  2.) // (7.0, 5.0)
("4", "3") +. ("3", "2") // ("43", "32")

答案 1 :(得分:6)

TL; DR; @AMieres的答案是真实的,这应该是注释,但注释的长度有限且代码格式不好__(ツ)_ /¯

使操作员扩展成为现实的工作正在进行中:IssueRFCPR一旦完成,以下操作可能终于起作用:

open System
open System.Runtime.CompilerServices

[<Extension>]
type TupleExtensions() =
    [<Extension>]
    static member inline (+) ((x1, y1), (x2, y2)) = (x1 + x2, y1 + y2)

// or

type Tuple<'T1, 'T2> with
    // warning FS1215: Extension members cannot provide operator overloads.
    // Consider defining the operator as part of the type definition instead.
    static member inline (+) ((x1, y1), (x2, y2)) = (x1 + x2, y1 + y2)

// and then

let t1 = (1., 2.)
let t2 = (42., 3.141)

TupleExtensions.(+) (t1, t2) // (43.0, 5.141)

// error FS0001: Expecting a type supporting the operator '+' but given a tuple type
t1 + t2