2013-04-08 1 views
10

я часто пишу код, который выглядит следующим образом:Кормление монадическое выражение в, если или когда

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

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

Возможно, лучший способ это:

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

Какой самый лучший подход здесь?

+5

Связывание 'unless' с' (>> =) 'можно сделать с помощью раздела,' 'что-то >> = (' unless' SomeAction) '', если 'someAction' коротка. Если он не короткий, я думаю: 'do bool <- что-то; если только bool $ не делает ничего лучше. –

+1

Вы можете использовать 'mfilter', который работает еще лучше, если вы встраиваете свои вычисления в' MaybeT'. –

ответ

5

Я мог бы определить вспомогательную функцию:

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

Похоже unlessM было бы очень полезно. Но тот факт, что я не вижу ничего подобного unlessM (или с этим типом подписи) в Hackage, заставляет меня думать, что есть какой-то лучший способ справиться с этой ситуацией, которую я еще не обнаружил. Что делают крутые дети?

+2

Вот его версия: http://hackage.haskell.org/packages/archive/cond/0.4.0.2/doc/html/Control-Conditional.html#v:unlessM –

+1

Существует ['extra'] (https : //hackage.haskell.org/package/extra-1.6/docs/Control-Monad-Extra.html), который также предоставляет 'exceptM' и, по-видимому, более активно поддерживается. –

5

Для таких случаев я использовал flip unless, но эти комбинации комбинаторов могут немного шуметь. С расширением LambdaCase вы могли бы, по крайней мере, избегать использования имени для результата doesFileExist, хотя это привело бы к необходимости сопоставления рисунков на True и False, что может показаться немного странным (в зависимости от того, считаете ли вы, что if не нужно или нет).

{-# 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?" 
Смежные вопросы