The GHC manual states this about monadic binding in GHCI:
Another important difference between the two types of binding is that the monadic bind (p <- e) is strict (it evaluates e), whereas with the let form, the expression isn't evaluated immediately:
(from here )
But I can do this in GHCI:
λ: x <- return $ error ":("
λ: :sprint x
x = _
This seems to show that the monadic bind is not strict. What am I missing?
Remember that a function being strict means f ⊥ = ⊥
. Consider:
ghci> x <- return undefined
-- no error
This means that return undefined >>= \\x -> ...
is not ⊥, but that doesn't really say anything about the strictness of >>=
, because of the return
. This, however:
ghci> y <- undefined
*** Exception: Prelude.undefined
is the case that the manual is referring to, and it shows that bind is strict in the left argument, because undefined >>= (\\y -> ...)
is ⊥. Finally,
ghci> :set -XBangPatterns
ghci> !z <- return undefined
*** Exception: Prelude.undefined
This line shows what happens if we give it a strict function as an argument, so we know that return undefined >>= f
is ⊥ if f
is strict . This actually follows from the monad law return x >>= f = fx
, so return ⊥ >>= f = f ⊥ = ⊥
In Haskell, we separate evaluation of values from execution of computations . return (error "")
is a computation that succeeds returning an undefined value, the value is not evaluated when bound. error "" :: IO a
is an undefined computation, that fails immediately.
I believe this is talking about the binding, ie the pattern matching process.
let p = e in e'
is equivalent to
case e of ~p -> e'
where the pattern p
has been changed into a lazy binding ~p
. Essentially, let
adds an implicit ~
in front of the pattern. For instance,
let [x] = [] in "hello"
evaluates to "hello"
, with no runtime errors.
In do
notation, a binding
do p <- e ; e'
gets transformed to something like
e >>= (\w -> case w of
p -> e'
_ -> fail "some message")
where w
is a fresh variable. Note that p
does not get a ~
here, otherwise it would always match and the _ -> fail ...
case would be unreachable.
This is needed to write eg
filterRight :: [Either a b] -> [a]
filterRight xs = do
Right x <- xs
return x
(which is a disguised list comprehension).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.