Cartesius00
Cartesius00

Reputation: 24414

Why is that not lazy

I'm still starting to explore Haskell. I know this code "runs" in the IO monad. When it goes from the l <- ... line to the next one, the IO - bind is called.

One could think that because Haskell is lazy, the l is never evaluated. But "bind" always evaluates the previous command, is that right? Because the program produces the "file-not-found" error.

main = do
    l <- mapM readFile [ "/tmp/notfound" ]
    return ()

Upvotes: 8

Views: 353

Answers (2)

sepp2k
sepp2k

Reputation: 370435

If you expand the do notation in your code, you get:

main = (mapM readFile ["/tmp/notfound"]) >>= (\l -> return ())

So yes, l is never evaluated, but that doesn't mean that the call to mapM is never evaluated. >>= always needs to evaluate its left operand in order to produce a value at least to some degree (at least in the IO monad and in any other monad that comes to mind).

Upvotes: 9

Daniel Fischer
Daniel Fischer

Reputation: 183978

One could think that because Haskell is lazy, the l is never evaluated.

Yes, and it never is evaluated. However, due to the definition of (>>=) in IO, the action readFile "/tmp/notfound" is executed, and that means the runtime tries to open the file. If there is no such file, a "File not found" error is raised. If there were such a file, it would be opened, but its contents would not be read until demanded. In the above, they are not demanded, so the contents will not be read.

What is evaluated here (and even executed) is the action producing l. Since the file doesn't exist, that raises an error.

Upvotes: 15

Related Questions