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?

+3


source to share


2 answers


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 >>?

.

+8


source


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.

+10


source







All Articles