map :: (a -> b) -> [a] -> [b]
fmap :: Functor f => (a -> b) -> f a -> f b
liftM :: Monad m => (a -> b) -> m a -> m b
Dlaczego mamy trzy różne funkcje, które zasadniczo robią to samo?
map :: (a -> b) -> [a] -> [b]
fmap :: Functor f => (a -> b) -> f a -> f b
liftM :: Monad m => (a -> b) -> m a -> m b
Dlaczego mamy trzy różne funkcje, które zasadniczo robią to samo?
map
i na liftM
pewno powinny robić dokładnie to samo, co fmap
.
fmap
i liftM
robią dokładnie to samo, map
oczywiście jest to tylko ich szczególny przypadek, tj. Coś innego. fmap id getLine
jest dobrze napisany, a map 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? ).
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.
- Typeklasopedia , strona 20
fmap
i liftM
istnieją, 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.
- Typeklasopedia , strona 33
Edycja: historia agustussa map
i fmap
:
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.
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żywam liftM2
, itp. także.
--fwarn-amp
która pomaga zaktualizować istniejący kod przejścia.