我想在Haskell中编写一个简单的程序.它应该基本上并行运行两个shell命令.这是代码:
import System.Cmd import System.Exit import Control.Monad exitCodeToBool ExitSuccess = True exitCodeToBool (ExitFailure _) = False run :: String -> IO Bool run = (fmap exitCodeToBool) . system main = liftM2 (&&) (run "foo") (run "bar")
但命令"foo"返回ExitFailure,我希望"bar"永远不会运行.不是这种情况!它们都运行并且都在控制台上显示错误.
同时
False && (all (/= 0) [1..])
评价完美; 这意味着不计算第二个参数.如何在我的应用程序中使用系统命令执行相同的操作?
我认为使用&&
条件执行是一种坏习惯.当然这只是一个理由,为做到这一点的事无副作用,喜欢的东西False && all (/=0) [1..]
,但是当有副作用这是相当confusionsome使他们依赖于这样一个隐藏的方式.(因为这种做法非常普遍,大多数程序员会立即认出来;但我不认为这是我们应该鼓励的,至少在Haskell中是这样.)
你想要的是一种表达方式:"执行一些行动,直到一个人屈服False
".
对于您的简单示例,我只是明确地这样做:
main = do e0 <- run "foo" when e0 $ run "bar"
或短:run "foo" >>= (`when` run "bar")
.
如果您想更广泛地使用它,最好以更一般的方式进行.简单地检查一个布尔条件不是很一般,你通常也想传递某种结果.传递结果是我们使用monad进行IO的主要原因,而不仅仅是原始动作的列表.
啊哈,单子!实际上,你需要的是IO monad,但是有一个额外的"kill switch":你要么做一系列的动作,每一个都可能有一些结果要传递,或者 - 如果它们中的任何一个失败 - 你就会中止整个事情.听起来很像Maybe
,对吧?
http://www.haskell.org/hoogle/?hoogle=MaybeT
import Control.Monad.Trans.Maybe run :: String -> MaybeT IO () run s = MaybeT $ do e <- system s return $ if exitCodeToBool e then Just () else Nothing main = runMaybeT $ do run "foo" run "bar"