2013-04-08 2 views
10

je me surprends souvent à écrire du code qui ressemble à ceci:Nourrir une expression monadique en moins ou lorsque

import System.Directory (doesFileExist) 
import Control.Monad (unless) 

example = do 
    fileExists <- doesFileExist "wombat.txt" 
    unless fileExists $ putStrLn "Guess I should create the file, huh?" 

Peut-être une meilleure façon est:

example2 = 
    doesFileExist "wombat.txt" >>= 
    (\b -> unless b $ putStrLn "Guess I should create the file, huh?") 

Quelle est la meilleure approche ici?

+5

Reliure à '' unless' avec (>> =) 'peut être fait avec une section,' 'quelque chose >> = (' unless' uneAction) '', 'si someAction' est courte. Si ce n'est pas court, je pense 'faire bool <- quelque chose; à moins que bool $ fasse quoi que ce soit de mieux. –

+1

Vous pouvez utiliser 'mfilter', ce qui fonctionne encore mieux si vous intégrez votre calcul dans' MaybeT'. –

Répondre

5

Je pourrais définir une fonction d'assistance:

unlessM :: Monad m => m Bool -> m() -> m() 
unlessM b s = b >>= (\t -> unless t s) 

example3 = unlessM (doesFileExist "wombat.txt") $ 
    putStrLn "Guess I should create the file, huh?" 

Il semble que unlessM serait très utile. Mais le fait que je ne vois rien comme unlessM (ou avec la signature de ce type) sur Hackage me fait penser qu'il existe une meilleure façon de gérer cette situation, que je n'ai pas encore découverte. Que font les enfants cool?

+2

En voici une version: http://hackage.haskell.org/packages/archive/cond/0.4.0.2/doc/html/Control-Conditional.html#v:unlessM –

+1

Il y a le ['extra'] (https : //hackage.haskell.org/package/extra-1.6/docs/Control-Monad-Extra.html) qui fournit également 'unlessM' et semble être maintenu plus activement. –

5

J'ai fait usage de flip unless pour de tels cas, mais ces types de combinateurs peuvent devenir un peu bruyants. Avec l'extension LambdaCase, vous pourriez au moins éviter d'utiliser un nom pour le résultat de doesFileExist, bien qu'il en résulterait de devoir faire correspondre le motif sur True et False, ce qui peut sembler un peu étrange (selon si vous croyez que if est inutile ou non).

{-# LANGUAGE LambdaCase #-} 
import System.Directory (doesFileExist) 
import Control.Monad (unless) 

example' = 
    doesFileExist "wombat.txt" >>= 
    flip unless (putStrLn "Guess I should create the file, huh?") 

example'' = 
    doesFileExist "wombat.txt" >>= \ case 
    True -> return() 
    False -> putStrLn "Guess I should create the file, huh?" 
Questions connexes