Как работает неидиоматическая глобальная перегрузка операторов?
Я хочу понять код изэтот ответ
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: 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
ошибка FS0003: это значение не является функцией и не может быть применено