How does non idiomatic global operator overloading work?

自古美人都是妖i 提交于 2019-12-01 23:30:12

Your second example doesn't work because F# doesn't automatically infer static member constraints with methods as it does with operators.

So yes, it's possible but you will have to write the constraints by hand, the compiler will not infer them for you:

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

The upper-case identifier you mentioned is matching a Discriminated Union of only one single case, so it will always succeed and the name of the case is the same name of the type. All this is to shorten just a bit the amount of code since that DU is a dummy type. If it's confusing here's an example with a normal class:

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

Your third example doesn't work because (!!) is an unary operator, not binary like ($)

More information about this old technique in this old blog.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!