2010-12-14 28 views
4

J'ai le code suivant:Y at-il une fonction standard pour "faire ceci si juste x"?

doIf :: (a -> IO()) -> Maybe a -> IO() 
doIf f x = case x of 
    Just i -> f i 
    Nothing -> return() 

main = do 
    mapM_ (doIf print) [Just 3, Nothing, Just 4] 

qui sorties:

3 
4 

En d'autres termes, les valeurs Just sont imprimées, mais Nothing valeurs provoquent aucune action. (Et n'interrompez pas le calcul.)

Existe-t-il une fonction standard comme celle-ci dans les bibliothèques Haskell? Aussi, cela peut-il être rendu plus générique? J'ai essayé de remplacer IO() avec m b mais alors return() ne fonctionne pas. Comment générez-vous généralement return() pour une monade? (Si possible ..) Peut-on généraliser le Maybe ici?

Enfin, puis-je supprimer complètement la fonction doIf? Puis-je avoir un opérateur < #> qui applique un argument sauf si Nothing?

print <#> Just 3 
print <#> Nothing 

génèrerait

3 

Mais je ne sais pas si cela est possible.

+0

En y repensant, je suppose que c'est une sorte de monade "avec". – Steve

Répondre

7

Votre doIf est un cas particulier de Data.Foldable.traverse_.

Vous pouvez généralement trouver ce genre de chose à travers Hoogle, mais il semble être un peu cassé pour le moment. La version de ligne de commande que j'ai installée sur mon système donne Data.Foldable.traverse_ comme premier résultat pour la requête (a -> IO()) -> Maybe a -> IO().


Et bien sûr, vous pouvez définir cet opérateur, il est juste (<#>) = doIf (ou (<#>) = Data.Foldable.traverse_).

+0

Merci, wow "traverse" n'est pas le nom que j'aurais pensé pour cette fonction. – Steve

+1

Cela a plus de sens pour les autres instances de Pliable/Traversable telles que les tableaux. Vous pouvez considérer une valeur Maybe comme une liste de longueur au plus une, auquel cas votre fonction "traverse" cette liste. –

+0

Donne un sens, merci. – Steve

17

Jetez un oeil à la fonction:

maybe :: b -> (a -> b) -> Maybe a -> b 

Vous avez presque écrit dans doIf sauf pour le fixe return()

+0

Aha, merci! Quelque part, je pensais au code monadique et je n'ai pas envisagé de regarder des fonctions qui n'avaient pas de signature "m b". – Steve

+1

Oui, et 'IO()' est juste un autre type, peut être 'b' ici. – dino

5

Pourriez-vous faire somthing le long des lignes de:

main = do 
    mapM_ print $ catMaybes [Just 3, Nothing, Just 4] 

Voir la documentation catMaybes.

(NB: code non testé)

+3

J'aime cette approche.Diviser le problème en problèmes plus petits et rester loin des IO plus longtemps. – dino