use*_*963 3 f# overloading operator-overloading operators
我想了解这个答案的代码
type Mult = Mult with
    static member inline ($) (Mult, v1: 'a list) = fun (v2: 'b list) -> 
        v1 |> List.collect (fun x -> v2 |> List.map (fun y -> (x, y))) : list<'a * 'b>
    static member inline ($) (Mult, v1:'a      ) = fun (v2:'a) -> v1 * v2 :'a
let inline (*) v1 v2 = (Mult $ v1) v2
Run Code Online (Sandbox Code Playgroud)
F#可以解决重载成员.(因为它不支持成员的currying).所以,我认为,它也适用于方法
但它没有:
type Mult = Mult with
        static member inline Do (Mult, v1: 'a list) = fun (v2: 'b list) -> 
            v1 |> List.collect (fun x -> v2 |> List.map (fun y -> (x, y))) : list<'a * 'b>
        static member inline Do (Mult, v1:'a      ) = fun (v2:'a) -> v1 * v2 :'a
    let inline (<.>) v1 v2 = (Mult.Do (Mult,v1)) v2
Run Code Online (Sandbox Code Playgroud)
根据此程序点之前的类型信息,无法确定方法"Do"的唯一重载.可能需要类型注释.候选人:静态成员Mult.Do:Mult:Mult*v1:^ a - >(^ a - > ^ a)当^ a :(静态成员(*):^ a*^ a - > ^ a),静态成员Mult.Do:Mult:Mult*v1:'a list - >('b list - >('a*'b)list)
$定义运算符的语法令人困惑.它接受大写标识符作为运算符的第一个参数,Visual Studio不会抱怨它
Mult被推断为mult类型,但令人惊讶的是这不起作用:
type Mult = Mult with
    static member inline (!!) (mlt:Mult, v1: 'a list) = fun (v2: 'b list) -> 
        v1 |> List.collect (fun x -> v2 |> List.map (fun y -> (x, y))) : list<'a * 'b>
    static member inline (!!) (mlt:Mult, v1:'a      ) = fun (v2:'a) -> v1 * v2 :'a
let inline (<!>) v1 v2 = (Mult !! v1) v2
Run Code Online (Sandbox Code Playgroud)
错误FS0003:该值不是函数,无法应用
您的第二个示例不起作用,因为F#不会像使用运算符一样使用方法自动推断静态成员约束.
所以是的,它是可能的,但您必须手动编写约束,编译器不会为您推断它们:
type Mult = Mult with
    static member inline Do (Mult, v1: 'a list) = fun (v2: 'b list) -> 
        v1 |> List.collect (fun x -> v2 |> List.map (fun y -> (x, y))) : list<'a * 'b>
    static member inline Do (Mult, v1:'a      ) = fun (v2:'a) -> v1 * v2 :'a
let inline impl m v1 v2 = ((^T or ^a) : (static member Do:^T* ^a->(^b-> ^c)) (m,v1)) v2
let inline (<.>) a b = impl Mult a b
Run Code Online (Sandbox Code Playgroud)
您提到的大写标识符只匹配一个案例的Discriminated Union,因此它将始终成功,并且案例的名称与该类型的名称相同.所有这些都是为了缩短代码量,因为DU是虚拟类型.如果这是令人困惑的,这是一个普通类的例子:
type Mult() = class end with
    static member inline ($) (_:Mult, v1: 'a list) = fun (v2: 'b list) -> 
        v1 |> List.collect (fun x -> v2 |> List.map (fun y -> (x, y))) : list<'a * 'b>
    static member inline ($) (_:Mult, v1:'a      ) = fun (v2:'a) -> v1 * v2 :'a
let inline (*) v1 v2 = (Mult() $ v1) v2
Run Code Online (Sandbox Code Playgroud)
你的第三个例子不起作用,因为它(!!)是一元运算符,而不是二进制运算符($)
在这个旧博客中有关这种旧技术的更多信息.