Ich habe zwei Funktionen, eine, die versucht, ein Token von einem Webservice zu bekommen und kann fehlschlagen, und eine, die versucht, dieses Token zu verwenden, um den Benutzernamen zu erhalten und kann fehlschlagen.Wie bindet man verschachtelte Monaden?
getToken :: IO (Maybe Token)
getUsername :: Token -> IO (Maybe String)
Ich möchte das Ergebnis von getToken nehmen und es zu getUsername
füttern. Wenn es nur IO
oder Maybe
gäbe, könnte ich einfach bind verwenden, aber da es verschachtelte Monaden gibt, kann ich nicht. Wie kann ich etwas schreiben, das zu getToken >>= getUsername :: IO (Maybe String)
äquivalent ist?
Allgemeiner, welche Funktion hat Typ m1 m2 a -> (a -> m1 m2 b) -> m1 m2 b
?
Bonus Frage: Wie würde ich das tun mit der Do-Notation in einem IO
Kontext?
type Token = String
getToken :: IO (Maybe Token)
getToken = undefined
getUsername :: Token -> IO (Maybe String)
getUsername = undefined
useToken :: IO (Maybe String)
useToken = do
token <- getToken
case token of
Just x -> getUsername x
Nothing -> return Nothing
Wenn Sie nicht do
Notation verwenden möchten, dann können Sie verwenden:
Die allgemeine Art und Weise Monaden zu kombinieren, ist Monade Transformatoren zu verwenden. In Ihrem Fall, "MaybeT" (http://hackage.haskell.org/package/transformers-0.4.2.0/docs/Control-Monad-Trans-Maybe.html#v:MaybeT) –
MaybeT ist in der Tat die beste Lösung hier . –
Es gibt im Allgemeinen keine Funktion vom Typ '(Monad m1, Monad m2) => m1 (m2a) -> (a -> m1 (m2b)) -> m1 (m2b)'. Das ist gemeint, wenn Leute sagen "Monaden komponieren nicht". Siehe auch [Konkretes Beispiel, das zeigt, dass Monaden in der Zusammensetzung nicht geschlossen sind] (http://stackoverflow.com/q/13034229/791604). –