Как я могу связать второй аргумент в функции, но не первый (элегантным способом)? - PullRequest
36 голосов
/ 29 декабря 2010

Есть ли в 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) аргумент функции?

Ответы [ 3 ]

32 голосов
/ 29 декабря 2010

flip, которая производит новую функцию с инвертированными первыми двумя аргументами, уже упоминалось как прямолинейное решение.

Однако стоит отметить, что Haskell определяет хороший синтаксис инфикса для бинарных операторов.

Прежде всего, это просто

sub = (-)

С круглыми скобками все операторы - тоже синтаксически - обычные функции. Теперь мы можем карри операторов с некоторым специальным синтаксисом. Привязка к первому операнду:

addOne = (1 +)

... и ко второму

half = (/ 2)

Таким образом, ваш код становится

map (-5) [1..5]

К сожалению, -5 является числовым литералом, но вы понимаете, в чем дело. :) Теперь, поскольку мы можем превратить любую функцию в бинарный оператор, поставив галочки вокруг него, как в

f x y == x `f` y

мы можем использовать этот специальный синтаксис оператора для записи

map (`sub` 5) [1..5]

<ч /> Примечание: Каррирование первого аргумента является распространенным, второй - как в вашем случае - прекрасно возможен. Но: я бы не стал этого делать для дальнейших аргументов. Функции на Haskell написаны в стиле, который являются общими для карри, и именно по этой причине.

Использование некоторого специального синтаксиса для дальнейших аргументов кажется мне слишком неявным. Просто используйте лямбду и дайте переменным описательные имена.

9 голосов
/ 29 декабря 2010

Для n = 2 только другой способ связывания:

mapSub5 x = map (`sub` 5) x
9 голосов
/ 29 декабря 2010

Как связать второй аргумент:

div2 = flip div 2

ghci> div2 10
5

В вашем случае вы можете написать

ghci> map (flip (-) 5) [1..5]
[-4,-3,-2,-1,0]

Обратите внимание, что в Haskell вы можете написать операторы в виде префикса как (-) Это так же, как sub в вашем вопросе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...