Вычерчивание порядка в Хаскеле - PullRequest
13 голосов
/ 24 сентября 2010

Есть ли элегантная запись для вычеркивания аргументов функции из порядка в Haskell?

Например, если вы хотите разделить 2 на все элементы списка, вы можете написать

map ((/) 2) [1,2,3,4,5]

Однако для разделения всех элементов списка кажется, что вам необходимо определить анонимную функцию

map (\x -> x/2) [1,2,3,4,5]

Анонимные функции быстро становятся громоздкими в более сложных случаях.Я знаю, что в этом случае map ((*) 0.5) [1,2,3,4,5] будет работать нормально, но мне интересно знать, есть ли у Haskell более элегантный способ каррирования аргументов функциивышел из строя?

Ответы [ 4 ]

16 голосов
/ 24 сентября 2010

В данном конкретном случае:

Prelude> map (/2) [1..5]
[0.5,1.0,1.5,2.0,2.5]

Мало того, что вы можете использовать инфиксный оператор в качестве обычной префиксной функции, вы также можете частично применить его в инфиксной форме. Аналогично, первый пример лучше записать как map (2/) [1..5]

Кроме того, есть flip, который не такой элегантный, но все же лучший вариант, доступный для обычных функций (когда вы не хотите превращать их в инфиксы с помощью обратных тиков):

Prelude> let div' = (/)
Prelude> div' 2 1
2.0
Prelude> flip div' 2 1
0.5
2 голосов
/ 24 сентября 2010

Я думаю, что вы ищете обобщенное решение, подобное схеме cut.Правильно?

Существует функция flip, которая инвертирует первые 2 аргумента функции.Могут быть другие функции, выполняющие аналогичную задачу (я не слишком хорош в Haskell ... пока).

2 голосов
/ 24 сентября 2010

Для вашего второго лямбда не нужна, просто используйте как:

map (/2) [1..5]

Форма (/ 2) просто означает, что вы хотите получить доступ ко второму параметру оператора. Это также возможно с первым аргументом (2/). Это называется section , и это действительно полезный хак, не только в коде гольф. Вы также можете использовать его в префиксных функциях, если вы используете их infix:

map (`div` 2) [1..5]

В более сложных случаях, таких как 3 или более аргументов, вы должны использовать лямбда-выражения, поскольку в большинстве случаев они становятся более читабельными.

0 голосов
/ 25 сентября 2010

Я недавно столкнулся с очень похожей проблемой , и мне не удалось найти элегантное решение, кроме использования вспомогательной функции для этого:

dbfunc f b c = (\a -> liftIO $ f a b c)
deleteAllRows = do
  ask >>= dbfunc run "delete from t1" []

По крайней мереэтот шаблон достаточно распространен в HDBC, поэтому dbfunc можно использовать повторно.

...