Haskell mappe ritorno una monade
Domanda
La funzione di ricerca in Data.Map e Data.IntMap attualmente valori di ritorno avvolto in Magari con la firma di tipo
lookup :: Ord k => k -> Map k a -> Maybe a
È utilizzato per avere il tipo più generale di
lookup :: (Monad m, Ord k) => k -> Map k a -> m a
mi rendo conto l'ex probabile riduce la necessità di specificazione del tipo di extra, ma quest'ultimo renderebbe molto più generale e permetterà di ricerca per essere utilizzato in list comprehension. Esiste un modo di imitare questo comportamento con la versione più recente, o dovrebbe devo utilizzare una versione precedente della libreria?
Soluzione
elementi di Don convertiti lift
Maybe
alle loro controparti generali Monad
, quindi forse dovrebbe essere chiamato convert
o generalize
o qualcosa del genere; -)
Se si desidera utilizzare lookup
principalmente in list comprehension e altre monadi che implementano una fail
, si potrebbe anche fare uso della mappatura del fallimento pattern match per fail
:
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"
Altri suggerimenti
quest'ultimo renderebbe molto più generale e consentire di ricerca da utilizzare in list comprehension
Quest'ultimo è anche più pericoloso, poiché la maggior parte delle classi monad definiscono sicuro come error
. Vale a dire, il caso comune di non trovare un elemento in Map è un errore di programma-di terminazione per la maggior parte monadi. Che, insieme con l'aumento della probabilità del contesto tipo sbagliato essere dedotta, mezzi si tende a scoraggiare lo stile 'monadici sicuro ritorno' ora.
C'è un modo di imitare questo comportamento con la versione più recente
In realtà non c'è! Basta sollevare Forse un in Monade una, in questo modo:
lift :: Monad m => Maybe a -> m a
lift Nothing = fail "you die now"
lift (Just a) = return a
E ora si può scrivere, ad esempio, lift . lookup
Per il caso specifico della lista Monade, la soluzione più semplice è quella di utilizzare 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"]