IO monad的逻辑和严格性 [英] Logical AND strictness with IO monad

查看:134
本文介绍了IO monad的逻辑和严格性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在Haskell中编写一个简单的程序。它应该基本上并行运行两个shell命令。这里是代码:

  import System.Cmd 
import System.Exit
import Control.Monad

exitCodeToBool ExitSuccess = True
exitCodeToBool(ExitFailure _)= False

run :: String - > IO Bool
run =(fmap exitCodeToBool)。系统

main = liftM2(&& amp; amp;)(runfoo)(runbar)

但命令foo返回ExitFailure,我希望bar永远不会运行。不是这种情况!他们都运行,并在控制台上显示错误。



同时

  False&& (all(/ = 0)[1 ..])

这意味着第二个参数不计算。我应该如何在系统命令中执行相同的操作?

; 用于条件执行是一个坏习惯。对于无副作用的东西,比如 False&&所有(/ = 0)[1 ..] ,但是当有副作用时,让它们依赖于这种隐藏的方式是相当混乱的。 (因为这种做法非常普遍,大多数程序员会立即认出它,但我认为这不是我们应该鼓励的事情,至少在Haskell中是这样。)



什么你想要的是一种表达方式:执行一些动作,直到出现 False



举个简单的例子,我只是明确地做到这一点:

  main = do 
e0< ; - 当e0 $ runbar时运行foo

或short:运行foo>> =(`when'runbar)



更广泛地使用这一点,以更一般的方式来做这件事很好。简单地检查一个布尔条件不是很一般,你通常也会想传递某种结果。传递结果是我们为IO使用monad的主要原因,而不仅仅是简单的动作列表。



Aha,monads!事实上,你需要的是IO monad,但是有一个额外的kill switch:要么执行一系列操作,每个操作都可能会传递一些结果,或者 - 如果其中任何一个失败 - 则会中止整个事件。听起来很像也许,对吗?



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 $做
运行foo
运行bar


I am trying to write a simple program in Haskell. It should basically run two shell commands in parallel. Here is the code:

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

But command "foo" returns ExitFailure and I expect "bar" never to run. This is not the case! They both run and both show errors on the console.

At the same time

False && (all (/= 0) [1..])

evaluates perfectly well; this means the second argument is not calculated. How do I do the same with system commands in my app?

解决方案

I think using && for conditional execution is something of a bad habit. Sure it's just a matter of reason to do this for side-effect-free stuff like the False && all (/=0) [1..], but when there are side-effects it's quite confusionsome to make them dependent in such a hidden way. (Because the practise is so widespread, most programmers will immediately recognise it; but I don't think it's something we should encourage, at least not in Haskell.)

What you want is a way to express: "execute some actions, until one yields False".

For your simple example, I'd just do it explicitly:

main = do
   e0 <- run "foo"
   when e0 $ run "bar"

or short: run "foo" >>= (`when` run "bar").

If you want to use this more extensively, it's good to do it in a more general manner. Simply checking a boolean condition is not very general, you'll normally also want to pass on some kind of result. Passing on results is the main reason we use a monad for IO, rather then simply lists of primitive actions.

Aha, monads! Indeed, what you need is the IO monad, but with an extra "kill switch": either you do a sequence of actions, each possibly with some result to pass on, or – if any of them fails – you abort the entire thing. Sounds a lot like Maybe, right?

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"

这篇关于IO monad的逻辑和严格性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆