2010-06-13 6 views
10

Die Funktion Lookup in Data.Map und Data.IntMap derzeit Werte zurück umwickelt Vielleicht mit der Art SignaturHaskell Karten eine Monade Rückkehr

lookup :: Ord k => k -> Map k a -> Maybe a 

Es verwendet, um die allgemeinere Art von

lookup :: (Monad m, Ord k) => k -> Map k a -> m a 
haben

Ich realisiere, dass ersteres wahrscheinlich die Notwendigkeit einer zusätzlichen Typspezifikation reduziert, aber letzteres würde es viel allgemeiner machen und ermöglichen, dass Nachschlagen in Listenkompressen verwendet wird. Gibt es eine Möglichkeit, dieses Verhalten mit der neueren Version nachzuahmen, oder müsste ich eine ältere Version der Bibliothek verwenden?

Antwort

5

Don lift wandelt Maybe ‚s Elemente ihrer allgemeinen Monad Kollegen, vielleicht sollte es convert oder generalize oder etwas ;-)

genannt werden, wenn Sie nur lookup hauptsächlich in Listenkomprehensionen und andere Monaden verwenden möchten daß das Gerät ein fail, 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" 
+1

Dies zeigt perfekt, warum die Verwendung von fail schlecht ist: es ist fast immer eine Programm Beendigung Ausnahme. Nicht was du willst, wenn du in Karten nachschaust. –

+0

Nun, ich sagte "Monaden, die einen Fehler implementieren", nicht ich? -) "Fehler" ist undefiniert ist nicht implementiert. Ich wollte diesen Fall auch nur illustrieren. Persönlich verwende ich Muster-Match-Fail in Do-Blöcke, wenn die Monade auch ein 'MonadPlus' ist und' fail' als 'mzero' implementiert. Das ist, wenn diese Technik am nützlichsten ist. – claus

19

letztere wäre es viel allgemeinere machen und erlauben Nachschlagen in Listenkomprehensionen verwendet werden

Letzteres ist auch nicht sicher, wie die Mehrheit der Monade Klassen als error scheitern definieren. Das heißt, der übliche Fall, in dem kein Element in der Map gefunden wird, ist ein Programmbeendigungsfehler für die meisten Monaden. Dies, zusammen mit der erhöhten Wahrscheinlichkeit, dass der falsche Typ-Kontext abgeleitet wird, bedeutet, dass wir dazu neigen, den "monadischen Fail Return" -Stil jetzt zu entmutigen.

Gibt es eine Möglichkeit, dieses Verhalten mit der neueren Version

Tat zu imitieren ist! 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

+0

Danke für die schnelle Antwort Don. Das ist viel prägnanter als das, was mir eingefallen ist. – sabauma

+0

Es könnte sinnvoll sein, diese Antwort zu aktualisieren, sobald die nächste Hauptversion von "base" herauskommt. Es sieht so aus als würde 'fail' endlich' Monad' verlassen und landet vielleicht in einem neuen 'MonadFail'. – dfeuer

4

Für die spezifische cas e der Liste monad, ist die einfachste Lösung zu verwenden maybeToList: