mem*_*xor 32 layout haskell rules
浏览https://wiki.haskell.org/IO_inside时,我遇到了以下评论和代码......
"而且,Haskell布局规则允许我们使用以下布局:
Run Code Online (Sandbox Code Playgroud)main = do a <- readLn if (a>=0) then return () else do print "a is negative" ...这可能有助于逃避冗长的"做"声明."
此后,我将使用符号C*来指代上述代码.
我认为C*的意图是读取一个数字,然后:
(i)如果它是非负的,则什么都不做.
(ii)如果是负数,则显示输出,表明它是.
我最初的反应是认为C*要么不能正确解析,要么不会按预期运行.
我认为布局会在第二个'do'之后立即插入一组空括号和一个分号,因为lexeme'print'的缩进比'a <中'a'所建立的当前布局上下文的缩进级别更多. - readLn".
也就是说,我对Layout生成的布局不敏感代码(以下称为C')的预测将类似于:
main = do {
a <- readLn;
if (a>=0) then return ()
else do {};
print "a is negative"
...
}
Run Code Online (Sandbox Code Playgroud)
我认为情况就是这样,基于Haskell 2010语言报告(https://www.haskell.org/onlinereport)第1部分第2.7节("词汇结构":'布局')中包含的以下句子./haskell2010/haskellpa1.html):
"如果紧跟在where,let,do或of之后的非括号lexeme的缩进小于或等于当前缩进级别,则插入空列表"{}"而不是开始布局,并且布局对当前级别进行处理(即插入分号或近括号)."
有关布局规则的更详细说明,请参见Haskell 2010语言报告第1部分(上面给出的URL)的第10.3节("语法参考":'布局').
在阅读这个更详细的说明时,我感到放心,我对Layout(即C')生成的布局不敏感代码的预测是正确的.
然而,令我惊讶的是,当我在GHCi中尝试上面规定的原始代码(即C*)时,它起作用(正确解析并按预期运行).
问题......
上面引用的句子(来自第2.7节)是否准确?
上面提到的布局规则(来自第10.3节)的详细说明是否准确?
我使用的推理中的缺陷是什么来达到我对由原始代码C*的Layout生成的布局不敏感代码(即C')的预测?
布局为上面规定的原始代码(即C*)生成的布局不敏感代码是什么,以及解释它的规则/原则是什么?
一般来说,有没有办法可以查看Layout生成的布局不敏感代码?如果是这样,它是什么(请详细说明/解释适合Haskell新手的技术,像我一样)?
kos*_*kus 26
这是GHC与Haskell标准默认或Haskell 98模式的已知和记录的偏差.
GHC有一个语言扩展名NondecreasingIndentation,可用于触发此行为.如果启用,则do即使下一个标记在与周围块相同的缩进级别开始,关键字也会引入新块.
如果您不想这样,请说-XNoNondecreasingIndentation或-XHaskell2010(或相应地使用语言编译指示).
您可以通过将-ddump-parsed标志传递给GHC 来查看GHC解析的代码的漂亮打印版本.这只会部分删除布局(对于do-block来说这样做,但不是为了让它),但可能仍然提供线索.