zer*_*kms 3 lambda haskell scope anonymous-function
我目前正在阅读"真实世界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)
Run Code Online (Sandbox Code Playgroud)
我无法得到的是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'
Run Code Online (Sandbox Code Playgroud)
那为什么它在代码中有用呢?
你可能会这样读:
(\(width, s) -> getNat s) >>? (\(height, s) -> getNat s) >>? ...
Run Code Online (Sandbox Code Playgroud)
在那种情况下,你是对的; 你不能访问那些超出范围的东西.但它实际上是这样的:
(\(width, s) -> ((getNat s) >>? (\(height, s) -> (getNat s) >>? (...))))
Run Code Online (Sandbox Code Playgroud)
用语言来说,这些表达并不是独立的; 它实际上是嵌套的,虽然它们的缩进没有清楚地表明它,你当然可以从外部范围访问东西.
要了解原因,请考虑将\x -> x + 5其解释为\x -> (x + 5)而不是(\x -> x) + 5.该\是在消费它的拉姆达身体非常贪婪,并在不会停止+,只是因为它不会在停止>>?.
| 归档时间: |
|
| 查看次数: |
156 次 |
| 最近记录: |