Haskell cartes de retour d'une monade
Question
La fonction de recherche dans Data.Map et Data.IntMap actuellement des valeurs de retour enveloppé dans Peut-être avec la signature de type
lookup :: Ord k => k -> Map k a -> Maybe a
Il l'habitude d'avoir le type plus général de
lookup :: (Monad m, Ord k) => k -> Map k a -> m a
Je me rends compte l'ancien probablement réduit le besoin de spécification de type supplémentaire, mais celui-ci serait beaucoup plus générale et permettre recherche à utiliser dans la liste compréhensions. Est-il possible d'imiter ce comportement avec la version plus récente, ou devrais-je utiliser une ancienne version de la bibliothèque?
La solution
lift
de Don convertit les éléments de la Maybe
à leurs homologues de Monad
général, donc peut-être qu'il devrait être nommé convert
ou generalize
ou quelque chose; -)
Si vous voulez juste utiliser lookup
principalement dans la liste et compréhensions autres monades qui mettent en œuvre un fail
, vous pouvez également utiliser la cartographie de l'échec de correspondance de motif à 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"
Autres conseils
ce dernier rendrait beaucoup plus générale et permettre recherche à utiliser dans la liste compréhensions
Ce dernier est aussi plus dangereuse, car la majorité des classes de monades définissent comme error
échouent. C'est, le cas fréquent de ne pas trouver un élément dans la carte est une erreur de terminaison de programme pour la plupart des monades. Cela, couplé à la probabilité accrue du contexte de mauvais type étant inférée, des moyens, nous avons tendance à décourager le style « échec Monadique retour » maintenant.
Est-il possible d'imiter ce comportement avec la nouvelle version
Il y a en effet! Il suffit de soulever Peut-être un dans Monad un, comme suit:
lift :: Monad m => Maybe a -> m a
lift Nothing = fail "you die now"
lift (Just a) = return a
Et vous pouvez maintenant écrire, par exemple lift . lookup
Pour le cas spécifique de la monade liste, la solution la plus simple est d'utiliser 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"]