我想了解this回答
中的代码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
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
无法基于确定方法“Do”的唯一重载 在此程序点之前键入信息。类型注释可以是 需要。候选人:静态成员Mult.Do:Mult:Mult * v1:^ a - &gt; (^ a - &GT; ^ a)当^ a :(静态成员(*):^ a * ^ a - &gt; ^ a),静态成员Mult.Do:Mult:Mult * v1:'a list - &gt; ('b list - &gt;('a *'b) 列表)
定义运算符$
的语法令人困惑。它接受大写标识符作为运算符的第一个参数,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
错误FS0003:此值不是函数且无法应用
答案 0 :(得分:6)
你的第二个例子不起作用,因为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
您提到的大写标识符只匹配一个案例的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
你的第三个例子不起作用,因为(!!)
是一元运算符,而不是像($)
这样的二进制
this old blog中有关此旧技术的更多信息。