2013-04-08 16 views
10

ich finde mich oft das Schreiben von Code, der wie folgt aussieht:Speicherung eines monadischen Ausdruck in, es sei denn, oder wenn

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

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

Vielleicht ein besserer Weg ist:

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

Was hier der beste Ansatz ist?

+5

Bindung an 'unless' mit' (>> =) 'mit einem Abschnitt erfolgen,' 'etwas >> = (' unless' someAction) '', wenn 'someAction' ist kurz. Wenn es nicht kurz ist, denke ich 'tu bool <- etwas; es sei denn, Bool $ macht was auch immer "ist besser. –

+1

Sie können 'mfilter' verwenden, was noch besser funktioniert, wenn Sie Ihre Berechnung in' MaybeT' einbetten. –

Antwort

5

Ich konnte eine Hilfsfunktion definieren:

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?" 

Es scheint wie unlessM sehr nützlich wäre. Aber die Tatsache, dass ich nichts wie unlessM (oder mit dieser Art Signatur) auf Hackage sehe, lässt mich denken, dass es einen besseren Weg gibt, mit dieser Situation umzugehen, eine, die ich noch nicht entdeckt habe. Was machen die coolen Kids?

+2

Hier ist eine Version davon: http://hackage.haskell.org/packages/archive/cond/0.4.0.2/doc/html/Control-Conditional.html#v:unlessM –

+1

Es gibt die ['extra'] (https : //hackage.haskell.org/package/extra-1.6/docs/Control-Monad-Extra.html) Paket, das auch 'ifangM' bereitstellt und anscheinend aktiver gepflegt wird. –

5

Ich habe flip unless für solche Fälle verwendet, aber diese Arten von Kombinatoren können ein wenig laut werden. Mit der Erweiterung LambdaCase könnten Sie zumindest vermeiden, einen Namen für das Ergebnis doesFileExist zu verwenden, obwohl dies dazu führen würde, dass das Muster auf True und False gemustert werden müsste, was ein wenig seltsam aussehen könnte (abhängig davon, ob Sie glauben, dass if unnötig ist oder nicht)).

{-# 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?" 
Verwandte Themen