为什么解析错误?缩进?

use*_*686 3 haskell indentation pattern-matching parse-error

我写了这段代码:

addNums key num = add [] key num
    where add res a:as b:bs
        | a == [] = res
        | otherwise = add res:(a+b) as bs
Run Code Online (Sandbox Code Playgroud)

在第3行,口译员说:

解析错误(可能是错误的缩进)

我找不到任何错误,既没有代码也没有缩进.我为每个标签放了四个空格.

注解:

即使这不编译:

addNums key num = add [] key num
    where add res a:as b:bs
            | a == [] = res
            | otherwise = add res:(a+b) as bs
Run Code Online (Sandbox Code Playgroud)

第2行:

模式中的解析错误:添加

ham*_*mar 9

Haskell中的主要压缩规则是,如果要在另一条线上继续定义,则必须进一步缩进而不是您定义的内容.在这种情况下,你的add函数的保护不那么缩进,所以这就是编译器所抱怨的.

忽略代码中的其他错误,缩进应该是这样的:

addNums key num = add [] key num
    where add res a:as b:bs
            | a == [] = res
            | otherwise = add res:(a+b) as bs
Run Code Online (Sandbox Code Playgroud)

另请注意,缩进的确切数量无关紧要,只是相对于正在定义的事物的连续行的缩进.

您的代码的另一个语法问题是您似乎误解了Haskell的优先规则.在Haskell中,函数应用程序比任何运算符都更紧密,所以在你的意思add res a:as b:bs是解析为.(add res a):(as b):bsadd res (a:as) (b:bs)

最后的问题是类型错误.的(:)操作者的类型a -> [a] -> [a],这意味着它需要的元件一个列表,并产生一个列表.在您的代码中res:(a+b),您似乎已将此反转,因为它res是一个列表并且a+b是元素.由于Haskell中没有运算符将单个元素附加到列表的末尾,因此您必须使用列表连接运算符(++) :: [a] -> [a] -> [a]:res ++ [a+b].

您还要将元素 a与警卫中的列表 进行比较[].这可能不是你的意思,(a:as)如果列表为空,模式将不匹配.对此最简单的解决方案是添加另一种模式而不是保护.

把所有这些放在一起,这段代码应该有希望做到你想要的:

addNums key num = add [] key num
    where add res [] _ = res
          add res (a:as) (b:bs) = add (res ++ [a+b]) as bs
Run Code Online (Sandbox Code Playgroud)

PS反复附加到列表的末尾并不是非常有效.事实上,它是O(n 2).您可能希望添加到前面,并在完成后反转列表.这是O(n).


参考文献: