我知道问题已被问到,但我不敢相信没有直接的答案.
我理解在(&&)中隐藏副作用是不好的,但在我的情况下,副作用只是在检查过时的世界(存在文件,检查修改时间等,询问用户是/否的问题) .
那么haskell的方法是什么样的,所以如果cond1为false,则不执行cond2.
cond1, cond2 :: IO bool
main = do
cond <- liftM2 (&&) con1 con2
if cond
then result1
else result2
Run Code Online (Sandbox Code Playgroud)
我期待类似cond <- all [con1, con2]或相当的东西,但我找不到任何东西.
我可以看到很多手动解决方案.我仍然感到疑惑,这个功能在某处并不存在.lazzy评估的一个优点是它不仅&&像C中的硬编码那样短路.在命令式模式下,Haskell甚至不能短路,这真的很奇怪&&.虽然,所有解决方案都以某种方式使用,如果短路评估.有没有办法制作通用的lazzy liftM2?
这就是做什么Pipes.Prelude.and,经过有效生成的条件和短路的惰性流,如果它们中的任何一个是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
Run Code Online (Sandbox Code Playgroud)
相关链接:
这与其他人所说的没有什么不同,但这不是最简单的只是模仿以下的定义and:
andM = foldr (&&&) (return True)
where ma &&& mb = ma >>= \p -> if p then mb else return p
Run Code Online (Sandbox Code Playgroud)
然后我们得到,说:
> 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
Run Code Online (Sandbox Code Playgroud)
如果andM没有“短路”,则未定义的单元格将被评估并返回异常。
这有点令人恼火,liftM2 (&&)没有像人们希望的那样发挥作用。
编辑:我刚刚注意到,正如人们所预料的那样,这是在monad-loops包http://hackage.haskell.org/package/monad-loops-0.4.2.1/docs/src/Control-Monad-Loops.html中定义的#和M