Haskell IO Monad内部短路和短路

Haskell IO Monad内部短路和短路,haskell,Haskell,我知道有人问过这个问题,但我不敢相信没有直接的答案 我理解在(&&)中隐藏副作用是不好的,但在我的例子中,副作用只是检查外部世界中的某些东西(文件的存在、检查修改时间等,询问用户是/否) 那么haskell的方法是什么呢,如果cond1为false,那么cond2就不会被执行 cond1, cond2 :: IO bool main = do cond <- liftM2 (&&) con1 con2 if cond then result1

我知道有人问过这个问题,但我不敢相信没有直接的答案

我理解在(&&)中隐藏副作用是不好的,但在我的例子中,副作用只是检查外部世界中的某些东西(文件的存在、检查修改时间等,询问用户是/否)

那么haskell的方法是什么呢,如果cond1为false,那么cond2就不会被执行

cond1, cond2 :: IO bool


main = do
   cond <- liftM2 (&&) con1 con2
   if cond
   then   result1
   else   result2
cond1,cond2::IO bool
main=do

cond您想要的操作很容易明确定义

shortCircuitAnd :: Monad m => m Bool -> m Bool -> m Bool
shortCircuitAnd x y = do
   r1 <- x -- perform effect of x
   if r1 
     then y -- perform effect of y and return result
     else return False -- do *not* evaluate or perform effect of y

这就是
Pipes.Prelude.和
所做的,检查有效生成的条件的惰性流,如果其中任何一个条件是
False
,则短路:

import Pipes (each)
import qualified Pipes.Prelude as Pipes

conds :: [IO Bool]
conds = ...

main = do
    cond <- Pipes.and (each conds >-> Pipes.sequence)
    print cond
导入管道(每个)
导入合格管道。作为管道的前奏曲
条件::[IO Bool]
条件=。。。
main=do
cond->Pipes.sequence)
打印条件
相关链接:


我们可以使用monad转换器,如
MaybeT
,它是
MonadPlus
的一个实例。其思想是使用
guard
False
结果转换为
mzero
s,从而停止计算。然后我们将得到的
可能
转换回
Bool

import Control.Monad.Trans
import Control.Monad.Trans.Maybe

effyand :: (Functor m, Monad m) => [m Bool] -> m Bool
effyand = fmap isJust . runMaybeT . mapM_ (lift >=> guard)

我会定义一个像这样的幺半群

newtype AllM m = AllM { getAllM :: m Bool }

instance (Monad m) => Monoid (AllM m) where
    mempty = AllM (return True)
    mappend (AllM u) (AllM v) = AllM $
        u >>= \x -> if x then v else return False

然后
getAllM。麦康卡特。map AllM$[con1,con2]

这与其他人所说的没有什么不同,但仅仅模仿
的定义不是最简单的吗

 andM = foldr (&&&) (return True)
  where ma &&& mb = ma >>= \p -> if p then mb else return p
然后我们得到,比如说:

 > let test1 = putStrLn "This test succeeds" >> return True
 > let test2 = putStrLn "This test fails" >> return  False
 > andM [test1,test2,undefined,undefined]
 This test succeeds
 This test fails
 False
如果
和m
没有“短路”,则未定义的单元格将被计算并返回异常

有点恼人的是
liftM2(&&)
并没有像人们所希望的那样工作


编辑:我刚刚注意到,正如人们所预料的,这是在
monad循环
包中定义的
r1和&r2实际上是
r2
,因为
r1
是由
if
保证的。因此,
do r1不使用任何特殊的组合词:
andM[]=return True
然后
andM(x:xs)=do b正如我下面所说,
andM
在monad循环库中定义,如果你希望找到像这样的东西,@Arthur没有看到更新。我认为最好给你的答案添加一点解释,而不是留下一段代码。
 > let test1 = putStrLn "This test succeeds" >> return True
 > let test2 = putStrLn "This test fails" >> return  False
 > andM [test1,test2,undefined,undefined]
 This test succeeds
 This test fails
 False