除非或何时将一个monadic表达式引入

mhw*_*bat 11 monads haskell

我经常发现自己编写的代码如下:

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

example = do
  fileExists <- doesFileExist "wombat.txt"
  unless fileExists $ putStrLn "Guess I should create the file, huh?"
Run Code Online (Sandbox Code Playgroud)

也许更好的方法是:

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

这里最好的方法是什么?

mhw*_*bat 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?"
Run Code Online (Sandbox Code Playgroud)

这似乎unlessM非常有用.但是我unlessM在Hackage上看不到任何类似(或带有那种类型签名)的事实让我觉得有一些更好的方法来处理这种情况,我尚未发现这种情况.酷孩子们做什么?

  • 这是它的一个版本:http://hackage.haskell.org/packages/archive/cond/0.4.0.2/doc/html/Control-Conditional.html#v:unlessM (2认同)

Sco*_*uff 5

我已经使用flip unless了这种情况,但这些类型的组合器可能会有点吵.有了LambdaCase扩展,你至少能避免使用名称的结果doesFileExist,虽然这将导致不得不模式匹配的TrueFalse,这看起来就有点怪(取决于如果您认为上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?"
Run Code Online (Sandbox Code Playgroud)