通用 F# 运算符的乐趣

Generic F# operators fun

这个问题遵循了 post 此处提出的想法:

我开始想知道是否可以定义一个以类似方式接受两个参数的通用运算符,就像它在我链接的 post 中呈现的那样?

例如:我一直在尝试实现一个 "AlmostEqual" 运算符 (=~),它适用于浮点数和我自己的类型,称为 "VectorDirection"。 按照这个想法,我创建了以下代码:

type AlmostEqual = AlmostEqual with
    static member ($) (AlmostEqual, (a,b) : float * float) = a >= b - Math.tol && a <= b + Math.tol    
    static member ($) (AlmostEqual, (vd1, vd2)) =
                        // my logic goes here - irrelevant for the general idea presented here

let inline (=~) x = AlmostEqual $ x

效果很好,但有一个严重的限制:它可以按以下方式使用:

(=~) (arg1, arg2)

这意味着更自然的使用方式:

arg1 =~ arg2  // wrong: (=~) complains it's in a wrong place and arg2 is not a tuple

不允许。我明白这个限制,但我真的找不到办法绕过它。

let inline (=~) (x,y) = ...

是一个以元组作为参数的函数,

let inline (=~) x y = ...

是一个有两个参数的函数。 如果你想使用一个函数作为中缀函数,它需要有两个参数。

正如另一个答案中所解释的,问题是元组参数与柯里化参数,通过这样定义你的函数将解决主要问题:

let inline (=~) x y = AlmostEqual $ (x, y)

无论如何,我建议您也更改您的成员定义,因为您可能会遇到通过对多态参数进行元组处理来解决重载问题。如果你 运行 遇到这些问题试试这个:

type AlmostEqual = AlmostEqual with
    static member ($) (AlmostEqual, a: float) = fun (b: float) -> // {your implementation}
    static member ($) (AlmostEqual, vd1     ) = fun vd2        -> // {your implementation}

let inline (=~) x y = (AlmostEqual $ x) y