Haskell Karten Zurückgeben einer Monade
Frage
Die Funktion Nachschlagen in Data.Map und Data.IntMap zur Zeit Rückgabewert in Vielleicht verpackt mit die Art Signatur
lookup :: Ord k => k -> Map k a -> Maybe a
Es verwendet, um die allgemeinere Art zu haben,
lookup :: (Monad m, Ord k) => k -> Map k a -> m a
merke ich, die ehemaligen wahrscheinlich die Notwendigkeit zusätzlicher Typ Spezifikation reduziert, aber diese würde es viel allgemeinere und erlaubt Lookup in Listenkomprehensionen verwendet werden. Gibt es eine Möglichkeit zu imitieren dieses Verhalten mit der neueren Version, oder hätte ich eine ältere Version der Bibliothek benutzen?
Lösung
Don lift
wandelt Maybe
die Elemente ihrer allgemeinen Monad
Kollegen, vielleicht sollte es convert
oder generalize
oder etwas benannt werden; -)
Wenn Sie nur lookup
hauptsächlich in Listenkomprehensionen und anderen Monaden verwenden mögen, die ein fail
implementieren, können Sie dort auch die Abbildung von Mustererkennung Ausfall fail
machen könnten:
Prelude> [ v | Just v <- return $ lookup "hi" [("ho","silver")] ] [] Prelude> [ v | Just v <- return $ lookup "ho" [("ho","silver")] ] ["silver"] Prelude> do Just v <- return $ lookup "hi" [("ho","silver")] ; print v *** Exception: user error (Pattern match failure in do expression at <interactive>:1:3-8) Prelude> do Just v <- return $ lookup "ho" [("ho","silver")] ; print v "silver"
Andere Tipps
letztere wäre es viel allgemeinere und erlauben machen Nachschlagen in Listenkomprehensionen verwendet werden
Letzteres ist auch unsicher, da die Mehrheit der Monade Klassen als error
scheitern definieren. Das heißt, der gemeinsame Fall von nicht ein Element in der Karte zu finden, ist ein Programm-Abschlussfehler für die meisten Monaden. Dies, gepaart mit der erhöhten Wahrscheinlichkeit des falschen Kontext abgeleitet werden, Mittel neigen wir dazu, die zu entmutigen ‚monadischen scheitern Rückkehr‘ -Stil jetzt.
Gibt es eine Möglichkeit zu imitieren dieses Verhalten mit der neueren Version
Tatsächlich gibt es! Heben Sie einfach Vielleicht ein in Monad, etwa so:
lift :: Monad m => Maybe a -> m a
lift Nothing = fail "you die now"
lift (Just a) = return a
Und jetzt können Sie schreiben, z.B. lift . lookup
Für den speziellen Fall der Liste Monade, die einfachste Lösung ist die Verwendung maybeToList
:
Prelude> :m +Data.Maybe -- Note: Use "import Data.Maybe" in a program file
Data.Maybe> [ v | v <- maybeToList $ lookup "hi" [("ho","silver")] ]
[]
Data.Maybe> [ v | v <- maybeToList $ lookup "ho" [("ho","silver")] ]
["silver"]