Uczę się Aplikacji Haskella. Wydaje mi się (prawdopodobnie się mylę), że pure
funkcja nie jest tak naprawdę potrzebna, na przykład:
pure (+) <*> [1,2,3] <*> [3,4,5]
można zapisać jako
(+) <$> [1,2,3] <*> [3,4,5]
Czy ktoś może wyjaśnić zalety tej pure
funkcji w porównaniu z jawnym mapowaniem fmap
?
haskell
applicative
Gil Shafriri
źródło
źródło
pure f <*> x
jest dokładnie taki sam jakfmap f x
. Jestem pewien, że istnieje jakiś powód, dla któregopure
został włączonyApplicative
, ale nie jestem do końca pewien, dlaczego.pure
pozwala na użycie, no cóż, „czystych” wartości w obliczeniach aplikacyjnych. Chociaż, jak poprawnie obserwować,pure f <*> x
jest taka sama jakf <$> x
, nie ma takiego ekwiwalent za, powiedzmyf <*> x <*> pure y <*> z
. (Przynajmniej nie sądzę.)Monoid
klasą - w którympure
odpowiadaMonoid
element tożsamości. (Sugeruje to, żeApplicative
bezpure
może być interesujące, ponieważSemigroup
- któreMonoid
niekoniecznie musi mieć tożsamość - wciąż jest używane. Właściwie, teraz myślę o tym, wydaje mi się, że PureScript ma dokładnie takąpure
klasę „Aplikacja bez ”, chociaż nie nie wiem, do czego służy).fmap (\f' x' z' -> f' x' y z') f <*> x <*> z
, tak myślę. Pomysł tkwi wApplicative
dokumentacji jako prawo „wymiany”.Applicative
niepure
istnieje jakApply
z półgrup .Odpowiedzi:
Jestem tutaj na granicy moich kompetencji, więc nie bierz tego dłużej niż jest, ale komentarz był trochę za długi.
Mogą istnieć praktyczne powody, aby dołączyć
pure
do klasy typu, ale wiele abstrakcji Haskella pochodzi z podstaw teoretycznych i uważam, żeApplicative
tak też jest. Jak mówi dokumentacja, jest to silny, luźny funktor monoidalny (więcej szczegółów na stronie https://cstheory.stackexchange.com/q/12412/56098 ). Przypuszczam, żepure
służy ona jako tożsamość , tak jakreturn
robi to dlaMonad
(który jest monoidem w kategorii endofunkcji ).Rozważ
pure
iliftA2
:Jeśli trochę zmrużysz oczy, możesz sobie wyobrazić, że
liftA2
jest to operacja binarna, a dokumentacja tego również stwierdza:pure
oznacza zatem odpowiednią tożsamość.źródło
Applicative
bezpure
byłby funktor półgrupowy zamiast monoidalnego.fmap
nie zawsze to wycina. W szczególnościpure
to, co pozwala ci przedstawićf
(gdzief
jestApplicative
), kiedy jeszcze go nie masz. Dobrym przykładem jestPobiera listę „akcji” generujących wartości i zamienia ją w akcję tworzącą listę wartości. Co się stanie, gdy na liście nie będzie żadnych działań? Jedynym rozsądnym rezultatem jest akcja, która nie generuje żadnych wartości:
Jeśli tego nie zrobiłeś
pure
, będziesz zmuszony wymagać niepustej listy działań. Na pewno możesz sprawić, że zadziała, ale to tak, jakbyś mówił o dodawaniu bez wspominania o 0 lub mnożeniu bez 1 (jak mówili inni, ponieważApplicative
są monoidalne). Będziesz wielokrotnie spotykać się z przypadkowymi przypadkami, które można łatwo rozwiązać,pure
ale zamiast tego musisz rozwiązać dziwne ograniczenia na wejściach i innych pomocnikach.źródło