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