通用F#操作员很有趣

时间:2015-03-07 13:14:30

标签: generics f# type-inference

此问题遵循此处发布的想法: Generic units in F#

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

例如:我一直在尝试实现一个“AlmostEqual”运算符(=〜),它与Floats和我自己的类型一起使用,称为“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

是不允许的。我理解这个限制,但我真的找不到一种方法来解决它。

2 个答案:

答案 0 :(得分:3)

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

是一个函数,它将一个元组作为参数和

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

是一个有两个参数的函数。 如果要将函数用作中缀函数,则需要使用两个参数。

答案 1 :(得分:1)

正如在另一个答案中所解释的那样,问题是由于有争议的参数,通过定义你的函数会解决主要问题:

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