Я хочу, чтобы понять код из 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 # может разрешить перегруженные член. (Потому что он не поддерживает каррирование членов). Таким образом, я должен, он должен работать для методов, а
Но это не так:
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 -> (^ a ->^a) когда^a: (статический член (*):^a *^a ->^a), статический член Mult.Do: Мульт: Мульт * v1: 'список -> (' список б -> ('а *' б) список)
синтаксис, в котором оператор $
определен сбивает с толку. Он принимает верхний идентификатор случая в качестве первого аргумента оператора и 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: Это значение не является функцией и не может быть применено.