haskell - 为什么要解析错误?缩进?

标签 haskell pattern-matching indentation parse-error

我写了这段代码:

addNums key num = add [] key num
    where add res a:as b:bs
        | a == [] = res
        | otherwise = add res:(a+b) as bs

在第 3 行,解释器说:

parse error (possibly incorrect indentation)



无论是代码还是缩进,我都找不到错误。我为每个选项卡放置了四个空格。

注解:

即使这样也无法编译:
addNums key num = add [] key num
    where add res a:as b:bs
            | a == [] = res
            | otherwise = add res:(a+b) as bs

第 2 行:

Parse error in pattern: add

最佳答案

Haskell 的主要缩进规则是,如果你想在另一行继续定义,它必须比你定义的内容进一步缩进。在这种情况下,您的add 的守卫函数的缩进较少,所以这就是编译器所提示的。

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

addNums key num = add [] key num
    where add res a:as b:bs
            | a == [] = res
            | otherwise = add res:(a+b) as bs

另请注意,缩进的确切数量无关紧要,只有连续行相对于所定义事物的缩进。

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

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

您还在比较元素 a到列表[]在你的保护下。这可能不是你的意思,模式 (a:as)如果列表为空,则不匹配。最简单的解决方案是添加另一个模式而不是你的 guard 。

把所有这些放在一起,这段代码应该能达到你的预期:
addNums key num = add [] key num
    where add res [] _ = res
          add res (a:as) (b:bs) = add (res ++ [a+b]) as bs

附言重复追加到列表的末尾不是很有效。事实上,它是 O(n2)。您可能希望添加到前面,并在完成后反转列表。这是 O(n)。

引用:
  • Indentation
  • Pattern matching
  • 关于haskell - 为什么要解析错误?缩进?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7178199/

    相关文章:

    haskell - 用于更新树结构的透镜或箭头?

    regex - 在正则表达式中,匹配字符串末尾或特定字符

    coding-style - PHPStorm switch 语句 'break' 缩进

    haskell - Haskell 的沙盒版本

    haskell - KRC和SASL对Haskell的影响?

    php - 从段落中找到匹配词的最有效方法

    r - 如何使用管道 (%>%) 运算符正确地使 vim 缩进 dplyr 代码?

    vim - 在 vim 中,编写 lisp/clojure 代码,如何在 let 中正确缩进绑定(bind)?

    haskell - Haskell抽象语法表达式的动态加载

    functional-programming - 为什么在 OCaml 中使用模式匹配