2014-12-14 3 views
3

Я в настоящее время чтения «Real World Haskell» и смущает одна функция реализована там:Область видимости анонимных функций

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) 

То, что я не могу получить то, как width, height и другие просочилась из анонимной функции и стал доступен в последнем выражении.

Точное место в RWH: http://book.realworldhaskell.org/read/code-case-study-parsing-a-binary-data-format.html#id624895

Упрощенный собственный кусок кода не удается, как я ожидал:

Prelude> (\x -> x) 5 + (\y -> x) 6 

<interactive>:4:22: Not in scope: `x' 

Так почему же он работает в коде?

ответ

8

Вы, наверное, читаете это так:

(\(width, s) -> getNat s) >>? (\(height, s) -> getNat s) >>? ... 

В этом случае, вы были бы правы; вы не можете получить доступ к тем вещам, которые недоступны. Но на самом деле это так:

(\(width, s) -> ((getNat s) >>? (\(height, s) -> (getNat s) >>? (...)))) 

На словах эти выражения не являются независимыми; он фактически вложен, хотя их отступы не показывают его четко, и вы, безусловно, можете получить доступ к вещам из внешнего пространства.

Чтобы понять, почему, считайте, что \x -> x + 5 используется как \x -> (x + 5), а не (\x -> x) + 5. \ очень жадна, потребляя его лямбда-корпус, и не останавливается на +, так же как он не остановится на >>?.

+0

Но не ''? 'Левый ассоциативный? Они даже объясняют это как «Другими словами,« a >>? B >>? C' будет оцениваться слева направо, так как «(a >>? B) >>? C')« – zerkms

+0

'>>? 'лево-ассоциативный, но' '' '' жадный и будет потреблять столько, сколько может; он не остановится, когда приблизится к другому '>>?'. – icktoofay

10

Каждое выражение лямбда extends as far to the right as possible.

Грамматика неоднозначна относительно размеров абстракций лямбда, Пусть выражения и условные обозначения. Неоднозначность разрешается с помощью мета-правила , что каждая из этих конструкций простирается вправо, как возможно .

выражения, которые используют width и height имеют те масштабы, потому что они находятся внутри лямбда, который ввел их.

Смежные вопросы