I know the question has been asked there but I can't believe there is no straight answer.
I understand it's not good to hide side-effect inside a (&&) but in my case the side-effect are just checking something in the outstide world (existence of a file, check modification time etc, ask user a yes/no quistion).
So what is the haskell way to something like this, so that cond2 is not executed if cond1 is false.
cond1, cond2 :: IO bool
main = do
cond <- liftM2 (&&) con1 con2
if cond
then result1
else result2
I was expecting something like cond <- all [con1, con2]
or equivalent, but I can't find anything.
I can see lots of manual solution. I'm still puzzled that this function doesn't exists somewhere.
One advantage of lazzy evaluation is it doesn't only short-circuit for hard-coded &&
like in C. It is really strange that when in imperative mode, Haskell can't even short-circuit &&
.
Although, all solution use somehow and if to short-circuit the evaluation. Is there not a way to make a generic lazzy liftM2
?
So, What is an IO Monad? IO Monad is simply a Monad which: Allows you to safely manipulate effects. Transform the effects into data and further manipulate it before it actually gets evaluated.
The I/O monad contains primitives which build composite actions, a process similar to joining statements in sequential order using `;' in other languages. Thus the monad serves as the glue which binds together the actions in a program.
The IO monad in Haskell is often explained as a state monad where the state is the world.
The IO type constructor provides a way to represent actions as Haskell values, so that we can manipulate them with pure functions. In the Prologue chapter, we anticipated some of the key features of this solution. Now that we also know that IO is a monad, we can wrap up the discussion we started there.
This is what Pipes.Prelude.and
does, going over a lazy stream of effectfully-generated conditionals and short-circuiting if any of them are 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
Relevant links:
This isn't different from what some others are saying, but isn't it simplest just to emulate the definition of and
:
andM = foldr (&&&) (return True)
where ma &&& mb = ma >>= \p -> if p then mb else return p
then we get, say:
> 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
If andM
didn't 'short-circuit', then the undefined cell would have been evaluated and returned an exception.
It is a little irritating that liftM2 (&&)
doesn't work as one hoped.
Edit: I just noticed that, as one might have expected, this is defined in the monad-loops
package http://hackage.haskell.org/package/monad-loops-0.4.2.1/docs/src/Control-Monad-Loops.html#andM
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With