do块中的Haskell缩进

do块中的Haskell缩进,haskell,functional-programming,Haskell,Functional Programming,我正在实现Hutton的《Haskell编程》一书中的算术表达式树示例,我发现一个语法错误: 分析错误(可能缩进不正确或括号不匹配) firstgrm=do t省略大括号的地方,Haskell使用;块由它们的缩进表示。对Haskell缩进的工作原理有一个很好的描述: 所有分组表达式必须完全对齐。在第一行,Haskell将表达式左侧的所有内容都计算为缩进,即使它不是空格 在您的示例中,有两个do块。里面的那个用大括号,外面的不用。您可以通过在外部do块中添加大括号来编译代码: firstgrm =

我正在实现Hutton的《Haskell编程》一书中的算术表达式树示例,我发现一个语法错误:

分析错误(可能缩进不正确或括号不匹配)


firstgrm=do t省略大括号的地方,Haskell使用;块由它们的缩进表示。对Haskell缩进的工作原理有一个很好的描述:

所有分组表达式必须完全对齐。在第一行,Haskell将表达式左侧的所有内容都计算为缩进,即使它不是空格

在您的示例中,有两个
do
块。里面的那个用大括号,外面的不用。您可以通过在外部
do
块中添加大括号来编译代码:

firstgrm = do { t <- secgrm;
             ( do { symbol "##";
               o <- firstgrm;
           return (O (t ## o));}
        +++ return t ) }

最明显的错误语法是悬空的分号,但整个事情看起来很奇怪。我的大脑不能很好地处理Haskell布局规则的细节,所以我倾向于对如何缩进代码非常厌烦。那
(+++)
操作符是什么?您可能会说服我,使用适当的间距和
(+++)
的定义,这应该是可行的,但它肯定不是惯用的…嗨,欢迎使用堆栈溢出。我认为这是一个很好的问题,受到了一些不必要的粗鲁评论。我希望下次我们能做得更好。我知道,如果人们看到我的意图,理解代码会有所帮助,但为此,我只是在质疑我的语法。
firstgrm = do { t <- secgrm;
             ( do { symbol "##";
               o <- firstgrm;
           return (O (t ## o));}
        +++ return t ) }
firstgrm = do t <- secgrm
              x t +++ return t
  where
    x t = do symbol "##"
             o <- firstgrm
             return (O (t ## o))