Можно сделать это без объявления чего-либо, но я согласен с Брайаном , что лямбда или пользовательская функция, вероятно, является лучшим решением .
Я считаю, что чаще всего это нужно для частичного применения деления или вычитания.
> let halve = (/) >> (|>) 2.0;;
> let halfPi = halve System.Math.PI;;
val halve : (float -> float)
val halfPi : float = 1.570796327
Обобщая, мы можем объявить функцию applySecond
:
> let applySecond f arg2 = f >> (|>) arg2;;
val applySecond : f:('a -> 'b -> 'c) -> arg2:'b -> ('a -> 'c)
Чтобы следовать логике, это может помочь определить функцию следующим образом:
> let applySecond f arg2 =
- let ff = (|>) arg2
- f >> ff;;
val applySecond : f:('a -> 'b -> 'c) -> arg2:'b -> ('a -> 'c)
Теперь f
- это функция от 'a
до 'b -> 'c
. Он состоит из ff
, функции от 'b -> 'c
до 'c
, которая является результатом частичного применения arg2
к оператору прямого конвейера. Эта функция применяет конкретное значение 'b
, переданное для arg2
к своему аргументу. Поэтому, когда мы сочиняем f
с ff
, мы получаем функцию от 'a
до 'c
, которая использует заданное значение для аргумента 'b
, и это именно то, что мы хотели.
Сравните первый пример выше со следующим:
> let halve f = f / 2.0;;
> let halfPi = halve System.Math.PI;;
val halve : f:float -> float
val halfPi : float = 1.570796327
Также сравните их:
let filterTwoDigitInts = List.filter >> (|>) [10 .. 99]
let oddTwoDigitInts = filterTwoDigitInts ((&&&) 1 >> (=) 1)
let evenTwoDigitInts = filterTwoDigitInts ((&&&) 1 >> (=) 0)
let filterTwoDigitInts f = List.filter f [10 .. 99]
let oddTwoDigitInts = filterTwoDigitInts (fun i -> i &&& 1 = 1)
let evenTwoDigitInts = filterTwoDigitInts (fun i -> i &&& 1 = 0)
В качестве альтернативы, сравните:
let someFloats = [0.0 .. 10.0]
let theFloatsDividedByFour1 = someFloats |> List.map ((/) >> (|>) 4.0)
let theFloatsDividedByFour2 = someFloats |> List.map (fun f -> f / 4.0)
Кажется, что лямбда-версии легче читать.