Riffing auf Sepp2k's Antwort, dies ist ein hervorragendes Beispiel, um den Unterschied zwischen Functor
und Monad
zu zeigen.
Die Standard Haskell Definition von Monad
geht so etwas (vereinfacht):
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Dies ist jedoch nicht die einzige Möglichkeit, die Klasse definiert worden sein könnte. Eine Alternative läuft wie folgt aus:
class Functor m => Monad m where
return :: a -> m a
join :: m (m a) -> m a
Da Sie >>=
in Bezug auf fmap
und join
definieren:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
ma >>= f = join (f <$> ma)
wir an dieser in einer vereinfachten Skizze des Problems aussehen werde, du bist hineinrennen. Was Sie tun kann wie folgt schematisiert werden:
ma :: IO a
f :: a -> IO b
f <$> ma :: IO (IO b)
Jetzt Sie stecken, weil Sie einen IO b
benötigen, und die Functor
Klasse hat keine Operation, die Sie dort von IO (IO b)
bekommen. Der einzige Weg, zu bekommen, wo Sie wollen, ist in Monad
zu tauchen und der join
Betrieb ist genau das, was es löst:
join (f <$> ma) :: IO b
Aber durch die join
/<$>
Definition von >>=
, ist dies das gleiche wie:
ma >>= f :: IO a
Beachten Sie, dass die Bibliothek Control.Monad
mit einer Version join
(in Bezug auf return
und (>>=)
geschrieben) geliefert wird; Sie könnten das in Ihre Funktion einfügen, um das gewünschte Ergebnis zu erhalten. Aber das Bessere ist zu erkennen, dass das, was Sie zu tun versuchen, grundsätzlich monadisch ist, und somit ist das <$>
nicht das richtige Werkzeug für den Job. Du fütterst das Ergebnis einer Handlung einem anderen; Das erfordert von Ihnen, dass Sie Monad
verwenden.
mein intuitives Gefühl es hilft es: 'RemoveFile' fügt 1 Effekt hinzu.wenn wir am Ende nur 1 Effekt haben wollen, müssen wir etwas mit 0 füttern. 'lst' hat bereits einen Effekt. Also müssen wir es zuerst entfernen, indem wir den Bind verwenden, der den Effekt ausführt, um den Wert mit dem Wert 0 zu erhalten – nicolas