Склад функцій Haskell (.) Та функціональних застосувань ($): правильне використання


129

Я читав Haskell в реальному світі , і я наближаюся до кінця, але питання стилю насміхувало, що стосується операторів (.)та ($)операторів.

Коли ви пишете функцію, що є складом інших функцій, ви записуєте її так:

f = g . h

Але коли ви застосовуєте щось до кінця цих функцій, я записую це так:

k = a $ b $ c $ value

Але книга написала б це так:

k = a . b . c $ value

Тепер для мене вони виглядають функціонально рівнозначними, вони роблять точно те саме в моїх очах. Однак чим більше я дивлюся, тим більше я бачу людей, що пишуть свої функції таким чином, як це робить книга: складати (.)спочатку, а потім лише в кінці використовувати, ($)щоб додати значення для оцінки партії (ніхто не робить це з багатьма доларовими композиціями) .

Чи є причина використання книг набагато кращою, ніж використання всіх ($)символів? Або є якась найкраща практика, яку я не отримую? Або це зайве, і я взагалі не повинен про це турбуватися?


4
Зауважте, що другий приклад можна зробити так:k = a $ b $ c value
Томас Едінг

1
Так, це може бути, як згадував Зіфре нижче, але я вирішив залишити його там, оскільки це нічого не шкодить і має сенс його (і тепер ваших) коментарів має сенс. Хоча, хоча. +1 :)
Роберт Массайолі

2
Ще один поширений підхід - це a . b $ c value , який мені подобається не так, як третій приклад, але економить кілька персонажів.
Джон Л

Відповіді:


153

Я думаю, що можу відповісти на це авторитетом.

Чи є причина використання книг набагато кращим, ніж використання усіх ($) символів?

Особливих причин немає. Ми з Брайаном воліємо зменшити шум лінії. .тихіше, ніж $. В результаті книга використовує f . g . h $ xсинтаксис.


3
Ну, я не можу сподіватися на кращу відповідь, ніж ця; від одного з самих авторів. :) І це має сенс, воно виглядає набагато тихіше на сторінці, коли я читаю. Позначення цього як відповідь, оскільки воно безпосередньо відповідає на питання. Дякую за відповідь; і, фактично, книга.
Роберт Массайолі

38
Не погоджуватися з автором, але, думаю, є ще одна більш помітна причина в ментальній моделі створення чогось, а не використання його. Користувачі Haskell, як правило, хочуть вважати f.g.hце новим розумним творінням f(g(h())). Тепер вони викликають нову, хоч і анонімну, функцію, яку вони створили, а не просто прив'язують великий словник збірних функцій, таких як користувач PHP.
Еван Керролл

1
Це цікаве твердження: "зменшити шум лінії" та "тихіше, ніж". Я ніколи не думав про мови програмування в цій термінології, але це має ідеальний сенс.
Рабарберські

53

Вони справді рівноцінні: майте на увазі, що $оператор, по суті, нічого не робить. f $ xоцінює до f x. Метою $є поведінка його непохитності: право-асоціативна та мінімальна пріоритетність. Видалення $та використання круглих дужок для групування замість пріоритету інфікування, фрагменти коду виглядають так:

k = a (b (c (value)))

і

k = (a . b . c) value

Причина віддати перевагу .версії над $версією - це та сама причина переваги обох над самою вище в дужці версією: естетична привабливість.

Хоча, хтось може задатися питанням, чи використання операторів infix замість дужок базується на підсвідомому спонуканні уникати будь-якої можливої ​​подібності з Lisp (просто жартую ... я думаю?).


38

Додам, що в f . g $ x, f . gце значуща синтаксична одиниця.

Тим часом, в Росії f $ g $ x, f $ gце не змістовна одиниця. Ланцюг $, можливо , більш важливо - першим отримати результат gз x, а потім зробити fйого, а потім зробити fooйого, то і т.д.

Тим часом ланцюг ., мабуть, декларативніший, і в деякому сенсі наближений до орієнтованого на потік даних потоку даних - складають ряд функцій і в кінцевому рахунку застосовують їх до чогось.


2
Я вивчаю Haskell (не кодував нічого значимого), але мені подобається думати про $ як про своєрідний "трубі" оператор. Його дуже схоже на термінал | труба (за винятком потоків даних справа наліво), але, як і термінальні процеси, кожен блок явно незалежний.
LostSalad

1
Очевидно, що $оператор поводиться аналогічно <|оператору у F #. Я вважаю, що обидва визначені однаково, насправді - у F # (<|) a b = a bта в Haskell a $ b = a b, які по суті є рівнозначними.
Том Галвін

@Quackmatic Досить впевнений, що це (<|) b a = a bу F #, оскільки він використовується як [1; 2; 3; 4; 5] <| List.map ((+) 1), якщо пам'ять служить.
Комітети BalinKingOfMoria Reinstate

@BalinKingOfMoria <|Оператор передає значення функції, а не передає функцію значення - ваш приклад коду |>замість цього буде працювати з оператором.
Том Галвін

@Quackmatic О. Не знав, що існує кілька версій (я дуже не використовував F #).
Відшкодування BalinKingOfMoria відновити

18

Для мене, я думаю, що відповідь - це (а) акуратність, як сказав Дон ; і (б) я виявляю, що коли я редагую код, моя функція може закінчитися безточним стилем, і тоді все, що мені потрібно зробити, - це видалити останнє, $а не повертатися назад і змінити все. Незначний момент, звичайно, але нікчемність.


Так, це вагомий привід написати це так, якщо ви хочете закінчити склад функції, то це швидше. :) Так, для економії натискань клавіш, але важливіше часу. +1
Роберт Массайолі

13

У цій темі haskell-cafe є цікаве обговорення цього питання . По- видимому , є меншість точка зору , яка вважає , що право асоціативності $є «просто неправильно» , і вибір f . g . h $ xбільш ніж f $ g $ h $ xодин з способів бічних крокової питання.


Гей, ви знайшли цілу дискусію з цього питання. Це приголомшливо, я зараз читаю. +1
Роберт Массайолі

2
Подібні аргументи тут: ghc.haskell.org/trac/haskell-prime/wiki/…
enrique

Зауважимо, що $!також є "прямо неправильна" правильна асоціативність - Чому саме $! оператор право-асоціативний? .
imz - Іван Захарящев

3

Це просто питання стилю. Однак те, як це робить книжка, має для мене більше сенсу. Він складає всі функції, а потім застосовує їх до значення.

Ваш метод просто виглядає дивно, а останній $непотрібний.

Однак це насправді не має значення. У Haskell зазвичай існує багато, багато правильних способів зробити те саме.


3
Я не помітив, що останній $ був непотрібним, але я повинен був. Дякую, і я залишу його там, щоб люди знали, що означає цей коментар.
Роберт Массайолі

0

Я усвідомлюю, що це дуже давнє питання, але я думаю, що є ще одна причина цього, про яку не було сказано.

Якщо ви декларуєте нову функцію без точки f . g . h, значення, яке ви передаєте, буде застосовано автоматично. Однак якщо ти пишеш f $ g $ h , це не вийде.

Я думаю, що автор вважає за краще метод композиції в тому, що це призводить до належної практики створення функцій.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.