2011-04-09 5 views
38

Disons que j'ai un certain nombre de fonctions:Utilisation de la Monade Peut-être en « inverse »

f :: a -> Maybe a 
g :: a -> Maybe a 
h :: a -> Maybe a 

Et je veux les composer de la façon suivante: Si les rendements f Rien, compute g. Si g ne renvoie rien, calculez h. Si l'un d'entre eux calcule Just a, arrêtez la chaîne. Et la composition entière (h, g, f) devrait bien sûr revenir. Ceci est l'inverse de l'utilisation typique de la monade Maybe, où généralement vous arrêtez de calculer si Nothing n'est pas retourné.

Quel est le langage Haskell pour enchaîner des calculs comme celui-ci?

Répondre

42

mplus est exactement ce que vous cherchez, une partie de la MonadPlus classe de types. Voilà sa définition:

instance MonadPlus Maybe where 
    mzero = Nothing 

    Nothing `mplus` ys = ys 
    xs  `mplus` _ys = xs 

Pour l'utiliser dans votre cas:

combined x = (f x) `mplus` (g x) `mplus` (h x) 
+10

Alternative (l'analogue pour foncteurs Applicative) serait aussi bien que '(<|>)' est le même que 'mplus' pour Maybe. –

+1

Ou vous pouvez utiliser Data.Generics.Aliases.orElse – Landei

3

Je suppose que vous voulez dire:

f,g,h:: a -> Maybe b 

En utilisant MonadPlus

f x `mplus` g x `mplus` h x 

Vous pouvez utiliser le StateT Monad:

f, g, h sont Reader ™ Maybe b (jusqu'à la ReaderT)

ou en utilisant MSUM:

function = runReaderT $ msum $ map ReaderT [f,g,h] 
4

mplus est probablement mieux, mais cela devrait fonctionner également:

import Data.List 
import Data.Maybe 
import Control.Monad 

join $ find isJust [f x, g y, h z]