Как связать второй аргумент в функции, но не первый (элегантным способом)?
Есть ли способ в Haskell связать второй аргумент, но не первый из функции без использования лямбда-функций или определения другой "локальной" функции?
Пример. У меня есть двоичная функция вроде:
sub :: Int -> Int -> Int
sub x y = x - y
Теперь, если я хочу связать первый аргумент, я могу сделать это с помощью (sub someExpression):
mapSubFrom5 x = map (sub 5) x
*Main> mapSubFrom5 [1,2,3,4,5]
[4,3,2,1,0]
Это отлично работает, если я хочу привязать первые n аргументов без "пробела".
Если я хочу связать второй аргумент, но не первый, два параметра, о которых я знаю, более подробные:
Либо через другую, локальную, функцию:
mapSub5 x = map sub5 x
where sub5 x = sub x 5
*Main> mapSub5 [1,2,3,4,5]
[-4,-3,-2,-1,0]
Или используя лямбда:
mapSub5 x = map (\x -> sub x 5) x
В то время как обе работают нормально, мне нравится элегантность "sub 5" и интересно, есть ли такой же элегантный способ привязать n-й (n > 1) аргумент функции?
Ответы
Ответ 1
flip
, который создает новую функцию с первыми двумя инвертированными аргументами, уже упоминался как решение для решения проблемы.
Однако стоит отметить, что Haskell определяет хороший синтаксис инфикса для двоичных операторов.
Прежде всего, это просто
sub = (-)
С круглыми скобками все операторы также являются синтаксически - обычными функциями. Теперь мы можем работать с операторами с некоторым специальным синтаксисом. Связывание с первым операндом:
addOne = (1 +)
... и ко второму
half = (/ 2)
Таким образом, ваш код становится
map (-5) [1..5]
К сожалению, -5
является числовым литералом, но вы получаете точку.:) Теперь, поскольку мы можем превратить любую функцию в двоичный оператор, поместив обратные элементы вокруг нее, как в
f x y == x `f` y
мы можем использовать этот специальный синтаксис оператора для записи
map (`sub` 5) [1..5]
<ч/" > Примечание.. Каррирование первого аргумента является общим, второе - как в вашем случае - возможно. Но: я бы этого не делал для дальнейших аргументов. Функции Haskell написаны в стиле, в котором общие для карри расположены именно по этой причине.
Использование некоторого специального синтаксиса для дальнейших аргументов кажется для меня слишком скрытым. Просто используйте лямбда и дайте переменным описательные имена.
Ответ 2
Для n = 2 только другой способ привязки:
mapSub5 x = map (`sub` 5) x
Ответ 3
Как связать второй аргумент:
div2 = flip div 2
ghci> div2 10
5
В вашем случае вы можете написать
ghci> map (flip (-) 5) [1..5]
[-4,-3,-2,-1,0]
Обратите внимание, что в Haskell вы можете писать операторы в форме префикса как (-)
. Это то же самое, что и sub
в вашем вопросе.