Подача монадического выражения до или после
Я часто нахожу, что пишу код, который выглядит так:
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?")
Какой лучший подход здесь?
Ответы
Ответ 1
Я мог бы определить вспомогательную функцию:
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
Я использовал 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?"