Действительно ли возможно в F# приправить средний аргумент функции карри?

Вот код, который хорошо работает:

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

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

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

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

7
задан Tomas Petricek 8 July 2010 в 00:39
поделиться

1 ответ

Функции ff и gg в вашем примере одинаковы - оператор pipelining задает значение для первого аргумента функции в правой части. В вашем примере функция в правой части - ff x, а с помощью оператора pipelining вы указываете значение для аргумента 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

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

8
ответ дан 7 December 2019 в 05:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: