Можно ли в F # каррировать средний аргумент функции? - PullRequest
7 голосов
/ 07 июля 2010

Вот код, который отлично работает:

let f x y z = x + y + z

let g x y = f x y
let h x z = z |> f x

Так что я могу написать выражение «h 1», и FSI отобразит:

val it : (int -> int -> int) = <fun:it@110-3>

Если я назову «h 1 2 3», аргументы применяются в правильном порядке.
Но если последний аргумент имеет другой тип, все становится иначе:

let ff x y (z : string) = x + y

let gg x y = ff x y
let hh x (z : string) = z |> ff x

Теперь последняя функция hh вызывает сообщение об ошибке:

Script.fsx (119,10): ошибка FS0001: несоответствие типов.Ожидая string -> 'a, но учитывая int -> string -> int.Тип string не совпадает с типом int

Я понимаю, почему это происходит - "z" добавляется к "ff x", делая его вторым аргументом.Но тогда я ожидал бы, что в первом примере выражение «h 1 2 3» не будет работать должным образом (выполняется как «f 1 3 2»).Но это работает просто отлично.

1 Ответ

8 голосов
/ 07 июля 2010

Функции ff и gg в вашем примере одинаковы - оператор конвейерной обработки предоставляет значение для первого аргумента функции в правой части.В вашем примере функция с правой стороны - ff x, и с помощью оператора конвейерной передачи вы указываете значение для аргумента y:

let ff x y (z : string) = 
  printfn "%s" z
  x + y

// These two functions are the same:
let gg x y = ff x y
let hh x y = y |> ff x

Нет стандартного синтаксиса для указания, кромеПервые параметры при использовании частичной функции приложения.Однако вы можете написать функцию более высокого порядка или пользовательский оператор для этого.Например:

// Takes a function 'f' of type 'b -> 'a -> 'c
// and a value 'v' of type 'a and creates a function
// that takes the first argument ('b -> 'c)
let (|*>) v f = (fun mid -> f mid v);;

let gg x y = ff x y     // Specifies arguments x and y
let hh x z = z |*> ff x // Specifies arguments x and z

Я назвал оператор |*>, чтобы обозначить, что он пропускает один аргумент.Вы можете определить операторы, которые определяют значение других аргументов аналогичным образом (например, |**>, чтобы пропустить первые два аргумента).

...