对 Haskell 的布局工具如何处理此代码感到困惑
Perplexed by how this code is processed by Haskell's Layout facility
在浏览https://wiki.haskell.org/IO_inside时,我遇到了以下评论和代码...
"Moreover, Haskell layout rules allow us to use the following layout:
main = do a <- readLn
if (a>=0) then return ()
else do
print "a is negative"
...
that may be useful for escaping from the middle of a longish 'do' statement."
以后我会用符号C*来指代上面的代码
我推测C*的本意是读入一个数,然后:
(i) 如果它是非负的,什么也不做。
(ii) 如果为负数,则显示输出表明它为负数。
我最初的反应是认为 C* 要么无法正确解析,要么无法按预期运行。
我认为 Layout 会在第二个 'do' 之后插入一组空的大括号和一个分号,因为 lexeme 'print' 的缩进不超过当前已建立的布局上下文的缩进级别通过 "a <- readLn" 中的 'a'。
也就是说,我对Layout生成的布局不敏感代码(以下简称C')的预测是这样的:
main = do {
a <- readLn;
if (a>=0) then return ()
else do {};
print "a is negative"
...
}
我认为情况会是这样,这是基于 Haskell 2010 年语言报告第 1 部分第 2.7 节 ('Lexical Structure' : 'Layout') 中包含的以下句子(https://www.haskell.org/onlinereport/haskell2010/haskellpa1.html):
"If the indentation of the non-brace lexeme immediately following a where, let, do or of is less than or equal to the current indentation level, then instead of starting a layout, an empty list “{}” is inserted, and layout processing occurs for the current level (i.e. insert a semicolon or close brace)."
Haskell 的第 1 部分(URL 以上给出)的第 10.3 节('Syntax Reference' : 'Layout')给出了布局规则的更详细说明2010年语言报告。
阅读这个更详细的说明后,我感到很放心,因为我对布局(即 C')生成的布局不敏感代码的预测是正确的。
然而,令我惊讶的是,当我在 GHCi 中尝试上面规定的原始代码(即 C*)时,它有效(正确解析并按预期运行)。
问题...
我上面引用的那句话(来自2.7节)准确吗?
上述Layout规则的详细说明(来自10.3节)是否准确?
我用来预测由 Layout 为原始代码 C* 生成的布局不敏感代码(即 C')的推理有哪些缺陷?
对于上面规定的原始代码(即对于C*),Layout产生的layout-insensitive代码是什么,解释它的规则/原则是什么?
总的来说,有没有办法可以查看Layout生成的布局不敏感代码?如果是,它是什么(请详细说明/解释适合 Haskell 新手的水平的技术,比如我)?
这是 known and documented deviation 默认的 Haskell 标准或 Haskell 98 模式的 GHC。
GHC 有一个名为 NondecreasingIndentation
的语言扩展,可用于触发此行为。如果启用,do
关键字会引入一个新块,即使下一个标记以与周围块相同的缩进级别开始也是如此。
如果您不想这样,请说 -XNoNondecreasingIndentation
或 -XHaskell2010
(或相应地使用语言编译指示)。
您可以通过将 -ddump-parsed
标志传递给 GHC 来查看 GHC 解析的代码的打印版本。这只会部分删除布局(它对 do 块这样做,但例如不是 let),但可能仍会提供线索。
在浏览https://wiki.haskell.org/IO_inside时,我遇到了以下评论和代码...
"Moreover, Haskell layout rules allow us to use the following layout:
main = do a <- readLn if (a>=0) then return () else do print "a is negative" ...
that may be useful for escaping from the middle of a longish 'do' statement."
以后我会用符号C*来指代上面的代码
我推测C*的本意是读入一个数,然后:
(i) 如果它是非负的,什么也不做。
(ii) 如果为负数,则显示输出表明它为负数。
我最初的反应是认为 C* 要么无法正确解析,要么无法按预期运行。
我认为 Layout 会在第二个 'do' 之后插入一组空的大括号和一个分号,因为 lexeme 'print' 的缩进不超过当前已建立的布局上下文的缩进级别通过 "a <- readLn" 中的 'a'。
也就是说,我对Layout生成的布局不敏感代码(以下简称C')的预测是这样的:
main = do {
a <- readLn;
if (a>=0) then return ()
else do {};
print "a is negative"
...
}
我认为情况会是这样,这是基于 Haskell 2010 年语言报告第 1 部分第 2.7 节 ('Lexical Structure' : 'Layout') 中包含的以下句子(https://www.haskell.org/onlinereport/haskell2010/haskellpa1.html):
"If the indentation of the non-brace lexeme immediately following a where, let, do or of is less than or equal to the current indentation level, then instead of starting a layout, an empty list “{}” is inserted, and layout processing occurs for the current level (i.e. insert a semicolon or close brace)."
Haskell 的第 1 部分(URL 以上给出)的第 10.3 节('Syntax Reference' : 'Layout')给出了布局规则的更详细说明2010年语言报告。
阅读这个更详细的说明后,我感到很放心,因为我对布局(即 C')生成的布局不敏感代码的预测是正确的。
然而,令我惊讶的是,当我在 GHCi 中尝试上面规定的原始代码(即 C*)时,它有效(正确解析并按预期运行)。
问题...
我上面引用的那句话(来自2.7节)准确吗?
上述Layout规则的详细说明(来自10.3节)是否准确?
我用来预测由 Layout 为原始代码 C* 生成的布局不敏感代码(即 C')的推理有哪些缺陷?
对于上面规定的原始代码(即对于C*),Layout产生的layout-insensitive代码是什么,解释它的规则/原则是什么?
总的来说,有没有办法可以查看Layout生成的布局不敏感代码?如果是,它是什么(请详细说明/解释适合 Haskell 新手的水平的技术,比如我)?
这是 known and documented deviation 默认的 Haskell 标准或 Haskell 98 模式的 GHC。
GHC 有一个名为 NondecreasingIndentation
的语言扩展,可用于触发此行为。如果启用,do
关键字会引入一个新块,即使下一个标记以与周围块相同的缩进级别开始也是如此。
如果您不想这样,请说 -XNoNondecreasingIndentation
或 -XHaskell2010
(或相应地使用语言编译指示)。
您可以通过将 -ddump-parsed
标志传递给 GHC 来查看 GHC 解析的代码的打印版本。这只会部分删除布局(它对 do 块这样做,但例如不是 let),但可能仍会提供线索。