Потреба в чистому в додатках


19

Я вивчаю додатки Haskell Мені здається (я, мабуть, помиляюся), що pureфункція насправді не потрібна, наприклад:

pure (+) <*> [1,2,3] <*> [3,4,5]

можна записати як

(+) <$> [1,2,3] <*> [3,4,5]

Чи може хтось пояснити перевагу, яку pureфункція забезпечує над явним відображенням fmap?


1
Ви маєте рацію - pure f <*> xточно так само, як fmap f x. Я впевнений, що є якась причина, чому pureїї включили Applicative, але я не зовсім впевнений, чому.
bradrn

4
Я не маю часу на відповідь, і не переконаний, що це все-таки зробить хорошим або завершеним, але одне спостереження: pureдозволяє використовувати, ну, "чисті" значення в додатковому обчисленні. Хоча, як ви правильно зауважуєте, pure f <*> xте саме f <$> x, що, скажімо, немає такого еквівалента f <*> x <*> pure y <*> z. (Принаймні, я так не думаю.)
Робін Зігмонд,

3
Як ще одне, більш теоретичне, обґрунтування - існує альтернативна формулювання, яка тісно пов’язує його з важливим Monoidкласом -, що pureвідповідає Monoidелементу тотожності. (Це говорить про те, що Applicativeбез цього не pureможе бути цікаво, оскільки Semigroup- що є Monoidбез обов'язково мати ідентичність - все ще використовується. Насправді, зараз я думаю про це, я, мабуть, нагадую, що PureScript має саме такий pureклас "Додаток без ", хоча я не Не знаю, для чого це використовується.)
Робін Зігмонд

2
@RobinZigmond fmap (\f' x' z' -> f' x' y z') f <*> x <*> z, я думаю. Ідея є в Applicativeдокументації як закон "обміну".
HTNW

3
@RobinZigmond Applicativeне pureіснує як Applyу напівгрупоїдів .
дуплод

Відповіді:


8

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

Можливо, для включення pureдо класу типів є практичні причини , але багато абстракцій Хаскелла випливають із теоретичних основ, і я вважаю, що це теж має місце Applicative. Як йдеться в документації, це сильний млявий моноїдний функтор (детальніше див. Https://cstheory.stackexchange.com/q/12412/56098 ). Я припускаю, що вона pureслужить ідентичністю , як returnі для Monad(що є моноїдом у категорії ендофанкторів ).

Розглянемо pureта liftA2:

pure :: a -> f a
liftA2 :: (a -> b -> c) -> f a -> f b -> f c

Якщо трохи примружити, ви, можливо, зможете уявити, що liftA2це двійкова операція, про що також йдеться в документації:

Підніміть бінарну функцію до дій.

pure, то є відповідна ідентичність.


6
Саме так. Applicativeбез pureцього не було б, hm, напівгруповий функтор замість моноїдного.
близько

20

fmapне завжди це ріже. Зокрема, pureце те, що дозволяє вам представити f(де fце є Applicative), коли ви цього ще не маєте. Хороший приклад - це

sequence :: Applicative f => [f a] -> f [a]

Він приймає список "дій", що виробляють значення, і перетворює його в дію, що створює список значень. Що відбувається, коли в списку немає дій? Єдиний розумний результат - це дія, яка не дає значень:

sequence [] = pure [] -- no way to express this with an fmap
-- for completeness
sequence ((:) x xs) = (:) <$> x <*> sequence xs

Якщо у вас цього не було pure, ви змушені будете вимагати не порожній список дій. Ви, безумовно, могли змусити його працювати, але це як говорити про додавання, не згадуючи 0 або множення без 1 (як говорили інші, тому що Applicatives моноїдні). Ви будете неодноразово стикатися з крайовими справами, які легко вирішити, pureале натомість повинні вирішуватися дивними обмеженнями на ваші входи та іншими засобами діапазону.

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