Meistens Geschichte. fmap unterscheidet sich aus pädagogischen Gründen von map, liftM unterscheidet sich aus historischen Gründen von fmap (nämlich Functor ist keine Superklasse von Monad)
luqui
12
Oh, und nur um klar zu sein: Sie tun nicht "im Wesentlichen" dasselbe. Beides mapund liftMsollte mit Sicherheit genau das Gleiche tun wie fmap.
CA McCann
2
Während fmapund liftMgenau das Gleiche tun, ist dies mapnatürlich nur ein Sonderfall, dh etwas anderes. fmap id getLineist gut getippt, wohingegen map id getLinees nicht ist.
Sie fragen sich vielleicht, warum wir eine separate Kartenfunktion benötigen. Warum nicht einfach die aktuelle Nur-Listen-Kartenfunktion abschaffen und stattdessen fmap in map umbenennen? Das ist eine gute Frage. Das übliche Argument ist, dass jemand, der gerade Haskell lernt, bei falscher Verwendung der Karte lieber einen Fehler über Listen als über Functors sieht.
fmapund liftMexistieren, weil Monaden in Haskell nicht automatisch Funktoren waren:
Die Tatsache, dass wir sowohl fmap als auch liftM haben, ist eine unglückliche Folge der Tatsache, dass die Monad-Typklasse keine Functor-Instanz benötigt, obwohl mathematisch gesehen jede Monad ein Functor ist. Fmap und liftM sind jedoch im Wesentlichen austauschbar, da es ein Fehler (eher in sozialer als in technischer Hinsicht) ist, dass jeder Typ eine Instanz von Monad ist, ohne auch eine Instanz von Functor zu sein.
So passiert es eigentlich nicht. Was passierte war, dass der Kartentyp verallgemeinert wurde, um Functor in Haskell 1.3 abzudecken. Dh in Haskell 1.3 wurde fmap map genannt. Diese Änderung wurde dann in Haskell 1.4 rückgängig gemacht und fmap wurde eingeführt. Der Grund für diese Änderung war pädagogisch; Wenn Anfängern Haskell beigebracht wurde, erschwerte der sehr allgemeine Kartentyp das Verstehen von Fehlermeldungen. Meiner Meinung nach war dies nicht der richtige Weg, um das Problem zu lösen.
Und aus meiner Sicht als jemand, der Haskell mehr als ein Jahrzehnt nach der von @augustss beschriebenen Änderung kennengelernt hat und viel Zeit damit verbracht hat, Menschen zu helfen, die die Sprache jetzt lernen, ist es überhaupt nicht klar, dass es überhaupt geholfen hat wie auch immer. Sicherlich nicht genug, um die nutzlose Redundanz auszugleichen (was selbst dazu führt, dass Leute Fragen wie diese stellen); Die FunctorKlasse ist zu häufig, um sie zu ignorieren, und Anfänger werden ohnehin oft durch Fehlermeldungen verwirrt!
CA McCann
10
Können wir nicht einfach entfernen liftM? Lassen Sie den Code brechen, wen interessiert das? Normalerweise dauert es weniger als 2 Tage, bis der Code auf Github repariert und dann bei Hackage hochgeladen wird. Oder bin ich wild und verrückt?
Tarrasch
1
@Tarrasch: Nicht jeder verwendet Github, nicht alle Pakete haben eine großartige Erfolgsbilanz, um rechtzeitig aktualisiert zu werden, und ich neige dazu, liftMsie eher in einem Do-Block zu verwenden, als fmapweil sie besser zu meiner Verwendung passen liftM2usw. auch.
@ L01man Ja das wird bald behoben. Der Applicative Monad Proposal (AMP) scheint in die nächste Version von Haskell überzugehen. GHC 7.8.3 verfügt über ein neues Flag, --fwarn-ampmit dessen Hilfe der vorhandene Code für den Übergang aktualisiert werden kann.
map
undliftM
sollte mit Sicherheit genau das Gleiche tun wiefmap
.fmap
undliftM
genau das Gleiche tun, ist diesmap
natürlich nur ein Sonderfall, dh etwas anderes.fmap id getLine
ist gut getippt, wohingegenmap id getLine
es nicht ist.Antworten:
map
existiert, um Operationen an Listen und aus historischen Gründen zu vereinfachen (siehe Was ist der Sinn der Karte in Haskell, wenn es eine fmap gibt? ).- Typeclassopedia , Seite 20
fmap
undliftM
existieren, weil Monaden in Haskell nicht automatisch Funktoren waren:- Typeclassopedia , Seite 33
Edit: agustuss 'geschichte von
map
undfmap
:- Was ist der Sinn der Karte in Haskell, wenn es eine Karte gibt?
quelle
Functor
Klasse ist zu häufig, um sie zu ignorieren, und Anfänger werden ohnehin oft durch Fehlermeldungen verwirrt!liftM
? Lassen Sie den Code brechen, wen interessiert das? Normalerweise dauert es weniger als 2 Tage, bis der Code auf Github repariert und dann bei Hackage hochgeladen wird. Oder bin ich wild und verrückt?liftM
sie eher in einem Do-Block zu verwenden, alsfmap
weil sie besser zu meiner Verwendung passenliftM2
usw. auch.--fwarn-amp
mit dessen Hilfe der vorhandene Code für den Übergang aktualisiert werden kann.