Cloudy visibility of anonymous functions
I am currently reading "Real World Haskell" and am confused about one implemented feature:
parseP5_take2 :: L.ByteString -> Maybe (Greymap, L.ByteString)
parseP5_take2 s =
matchHeader (L8.pack "P5") s >>?
\s -> skipSpace ((), s) >>?
(getNat . snd) >>?
skipSpace >>?
\(width, s) -> getNat s >>?
skipSpace >>?
\(height, s) -> getNat s >>?
\(maxGrey, s) -> getBytes 1 s >>?
(getBytes (width * height) . snd) >>?
\(bitmap, s) -> Just (Greymap width height maxGrey bitmap, s)
I can't figure out how tags width
, height
and others have leaked out of the scope of anonymous functions and become available in the last expression.
Exact place in RWH: http://book.realworldhaskell.org/read/code-case-study-parsing-a-binary-data-format.html#id624895
The simplified native part of the code fails as I expect:
Prelude> (\x -> x) 5 + (\y -> x) 6
<interactive>:4:22: Not in scope: `x'
So why does it work in its code?
source to share
You are probably reading this:
(\(width, s) -> getNat s) >>? (\(height, s) -> getNat s) >>? ...
In that case, you are right; you cannot access those things that are not available. But in fact it is like this:
(\(width, s) -> ((getNat s) >>? (\(height, s) -> (getNat s) >>? (...))))
In words, these expressions aren't independent; it's actually nested, although their indentation doesn't show it clearly, and you can certainly access things from outside space.
To understand why, is \x -> x + 5
interpreted as \x -> (x + 5)
rather than (\x -> x) + 5
. \
is very greedy at consuming his lambda body and doesn't usually stop at +
, just like he doesn't stop at >>?
.
source to share
Each lambda expression extends as far to the right as possible .
The grammar is ambiguous about the scope of lambda abstractions, be it expressions and conventions. The ambiguity is resolved by the meta-rule that each of these constructs extends as far to the right as possible.
In expressions that use width
and height
, there are those that are in scope because they are inside the lambda that injected them.
source to share