Состав функции Haskell (.) И функциональное приложение ($) идиомы: правильное использование
Я читал "Real World Haskell", и я близился к концу, но вопрос стиля был в том, что он меня обманывал с операторами (.)
и ($)
.
Когда вы пишете функцию, являющуюся композицией других функций, вы пишете ее так:
f = g . h
Но когда вы применяете что-то к концу этих функций, я пишу его так:
k = a $ b $ c $ value
Но книга написала бы вот так:
k = a . b . c $ value
Теперь для меня они выглядят функционально эквивалентными, они делают то же самое в моих глазах. Тем не менее, чем больше я смотрю, тем больше я вижу, как люди записывают свои функции так, как это делает книга: сначала создайте с (.)
, а затем только в конце используйте ($)
, чтобы добавить значение для оценки партии (никто не делает это со многими долларовыми композициями).
Есть ли причина использовать книги, которые намного лучше, чем использование всех символов ($)
? Или здесь есть какая-то лучшая практика, которую я не получаю? Или это лишнее, и я не должен беспокоиться об этом вообще?
Ответы
Ответ 1
Думаю, я могу ответить на этот вопрос от авторитета.
Есть ли причина использовать книги, которые намного лучше, чем использование всех ($) символов?
Нет особых причин. Брайан и я оба предпочитаем уменьшать линейный шум. .
более тихий, чем $
. В результате в книге используется синтаксис f . g . h $ x
.
Ответ 2
Они действительно эквивалентны: имейте в виду, что оператор $
, по сути, ничего. f $ x
оценивается как f x
. Целью $
является ее поведение по фиксированности: право-ассоциативный и минимальный приоритет. Удаляя $
и используя скобки для группировки вместо приоритета infix, фрагменты кода выглядят следующим образом:
k = a (b (c (value)))
и
k = (a . b . c) value
Причиной предпочтения версии .
по версии $
является та же самая причина для предпочтения как в самой версии в скобках выше: эстетическая привлекательность.
Хотя некоторые могут задаться вопросом, использует ли операторы infix вместо круглых скобок какое-то подсознательное стремление избегать любого возможного сходства с Lisp (просто шучу... я думаю?).
Ответ 3
Я бы добавил, что в f . g $ x
, f . g
- значимая синтаксическая единица.
Между тем, в f $ g $ x
, f $ g
не является значимой единицей. Цепочка $
, возможно, более важна - сначала получите результат g
of x
, затем сделайте f
к ней, затем сделайте foo
к ней, затем и т.д.
Между тем цепочка .
, возможно, более декларативная и в некотором смысле ближе к центральному представлению потока данных - состоит из ряда функций и в конечном итоге применит их к чему-то.
Ответ 4
Для меня, я думаю, что ответ: (a) аккуратность, поскольку Дон сказал; и (б) я нахожу, что когда я редактирую код, моя функция может закончиться стилем без точек, а затем все, что мне нужно сделать, это удалить последний $
вместо того, чтобы возвращаться и изменять все. Небольшая точка, конечно, но тонкая.
Ответ 5
Здесь интересное обсуждение этого вопроса на этой теме haskell-cafe. По-видимому, существует точка зрения меньшинства, которая утверждает, что правая ассоциативность $
"просто неправильно" и выбирая f . g . h $ x
над f $ g $ h $ x
является одним из способов устранения проблемы.
Ответ 6
Это просто вопрос стиля. Однако способ, которым это делает книга, имеет больше смысла для меня. Он объединяет все функции и затем применяет их к значению.
Ваш метод выглядит странно, а последний $
не нужен.
Однако это действительно не имеет значения. В Haskell обычно существует много и много правильных способов сделать то же самое.
Ответ 7
Я понимаю, что это очень старый вопрос, но я думаю, что есть еще одна причина этого, о которой не упоминалось.
Если вы объявляете новую функцию без точек f . g . h
, значение, которое вы передаете, будет автоматически применено. Однако, если вы пишете f $ g $ h
, это не сработает.
Я думаю, что причина, по которой автор предпочитает метод композиции, заключается в том, что он приводит к хорошей практике создания функций.