Głównie historia. fmap różni się od mapy ze względów pedagogicznych, liftM różni się od fmap z powodów historycznych (mianowicie Functor nie jest superklasą Monady)
luqui
12
Aha, i tylko po to, by mieć jasność: „zasadniczo” nie robią tego samego. Oba mapi na liftMpewno powinny robić dokładnie to samo, co fmap.
CA McCann
2
Chociaż fmapi liftMrobią dokładnie to samo, mapoczywiście jest to tylko ich szczególny przypadek, tj. Coś innego. fmap id getLinejest dobrze napisany, a map id getLinenie jest.
Możesz zapytać, dlaczego potrzebujemy oddzielnej funkcji mapy. Dlaczego po prostu nie zrezygnować z obecnej funkcji mapowania tylko jako listy i zamiast tego zmienić nazwę fmap na map? Cóż, to dobre pytanie. Zwykłym argumentem jest to, że ktoś, kto dopiero uczy się Haskella, kiedy używa mapy nieprawidłowo, wolałby raczej zobaczyć błąd dotyczący list niż Functorów.
fmapi liftMistnieją, ponieważ monady nie były automatycznie funktorami w Haskellu:
Fakt, że mamy zarówno fmap, jak i liftM, jest niefortunną konsekwencją faktu, że klasa typu Monad nie wymaga instancji Functor, mimo że matematycznie każda monada jest funktorem. Jednak fmap i liftM są zasadniczo wymienne, ponieważ błędem (raczej w sensie społecznym niż technicznym) jest bycie instancją Monady bez bycia instancją Functora.
Tak się nie dzieje. Stało się tak, że typ mapy został uogólniony, aby objąć Functor w Haskell 1.3. To znaczy, w Haskell 1.3 fmap nazywał się map. Ta zmiana została następnie cofnięta w Haskell 1.4 i wprowadzono fmap. Powód tej zmiany był pedagogiczny; podczas nauczania Haskella początkującym bardzo ogólny typ mapy utrudniał zrozumienie komunikatów o błędach. Moim zdaniem nie był to właściwy sposób rozwiązania problemu.
I z mojej perspektywy jako kogoś, kto pierwszy raz zetknął się z Haskellem ponad dekadę po dokonaniu zmiany opisanej przez @augustss i spędził dużo czasu pomagając ludziom, którzy teraz uczą się tego języka, nie jest wcale jasne, czy to nawet pomogło tak czy siak. Z pewnością nie wystarczy, aby zrównoważyć bezużyteczną redundancję (która sama prowadzi do zadawania takich pytań jak to); Functorklasa jest zbyt powszechne ignorowanie, a początkujący są często mylone przez komunikaty o błędach w każdym razie!
CA McCann
11
Nie możemy po prostu usunąć liftM? Niech kod się zepsuje, kogo to obchodzi, naprawienie kodu na githubie i przesłanie go na hakowanie zajmuje zwykle mniej niż 2 dni. A może jestem dziki i szalony?
Tarrasch
1
@Tarrasch: nie wszyscy używają github, nie wszystkie pakiety mają świetne wyniki w zakresie aktualizacji na czas, a ja na przykład używam raczej liftMw trybie do-block, niż fmapdlatego, że lepiej pasuje do tego, kiedy używam liftM2, itp. także.
@ L01man Tak, to wkrótce zostanie naprawione. Aplikacyjnych Monada Wniosek (AMP) wygląda to przejdzie do następnej wersji Haskell. GHC 7.8.3 ma nową flagę, --fwarn-ampktóra pomaga zaktualizować istniejący kod przejścia.
map
i naliftM
pewno powinny robić dokładnie to samo, cofmap
.fmap
iliftM
robią dokładnie to samo,map
oczywiście jest to tylko ich szczególny przypadek, tj. Coś innego.fmap id getLine
jest dobrze napisany, amap id getLine
nie jest.Odpowiedzi:
map
istnieje, aby uprościć operacje na listach i ze względów historycznych (zobacz Jaki jest sens mapy w Haskell, kiedy jest fmap? ).- Typeklasopedia , strona 20
fmap
iliftM
istnieją, ponieważ monady nie były automatycznie funktorami w Haskellu:- Typeklasopedia , strona 33
Edycja: historia agustussa
map
ifmap
:- Jaki jest cel mapy w Haskell, kiedy jest fmap?
źródło
Functor
klasa jest zbyt powszechne ignorowanie, a początkujący są często mylone przez komunikaty o błędach w każdym razie!liftM
? Niech kod się zepsuje, kogo to obchodzi, naprawienie kodu na githubie i przesłanie go na hakowanie zajmuje zwykle mniej niż 2 dni. A może jestem dziki i szalony?liftM
w trybie do-block, niżfmap
dlatego, że lepiej pasuje do tego, kiedy używamliftM2
, itp. także.--fwarn-amp
która pomaga zaktualizować istniejący kod przejścia.