为什么解析错误?缩进?

发布于 2024-12-01 05:32:21 字数 593 浏览 1 评论 0原文

我写了这段代码:

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

在第 3 行,解释器说:

解析错误(可能是缩进不正确)

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

注释:

即使这样也不能编译:

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

第 2 行:

模式解析错误:添加

I wrote this code:

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

At line 3 the interpreter says:

parse error (possibly incorrect indentation)

I could not find something wrong, neither with the code nor with the indentation. I put four spaces for each tab.

Annotation:

Even this does not compile:

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

Line 2:

Parse error in pattern: add

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

青瓷清茶倾城歌 2024-12-08 05:32:21

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 中,函数应用程序的绑定比任何运算符都更紧密,因此 add res a:as b:bs 被解析为 (add res a):(as b) :bs,而您的意思是添加 res (a:as) (b:bs)

最后的问题是类型错误。 (:) 运算符的类型为 a ->; [一]-> [a],这意味着它需要一个元素一个列表,并生成一个列表。在您的代码 res:(a+b) 中,您似乎将其颠倒过来,因为 res 是一个列表,而 a+b 是元素。由于 Haskell 中没有运算符可以将单个元素附加到列表的 end 上,因此您必须使用列表串联运算符 (++) :: [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

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


参考文献:

The main indendation rule in Haskell is that if you want to continue a definition on another line, it has to be further indented than the the thing you're defining. In this case the guards for your add function are less indented, so that's what the compiler is complaining about.

Disregarding the other errors in your code, the indentation should be something like this:

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

Also note that the exact amount of indentation does not matter, only the indentation of the continuing lines relative to the thing being defined.

Another syntactic problem with your code is that you seem to have misunderstood the precedence rules of Haskell. In Haskell, function application binds tighter than any operator, so add res a:as b:bs is parsed as (add res a):(as b):bs, while you meant add res (a:as) (b:bs).

The final problems are type errors. The (:) operator has the type a -> [a] -> [a], which means that it takes an element and a list, and produces a list. In your code res:(a+b), you appear to have this reversed, as res is a list and a+b is the element. Since there is no operator in Haskell to append a single element to the end of a list, you'll have to use the list concatenation operator (++) :: [a] -> [a] -> [a] instead: res ++ [a+b].

You're also comparing the element a to the list [] in your guard. This is probably not what you meant, and the pattern (a:as) would not match if the list was empty. The easiest solution to this is to add another pattern instead of your guard.

Putting all of this together, this code should hopefully do what you intended:

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

P.S. Repeatedly appending to the end of a list is not very efficient. In fact, it's O(n2). You might want to add to the front instead and reverse the list when you're done. This is O(n).


References:

兔小萌 2024-12-08 05:32:21

出现缩进错误是因为您需要将 where 子句中的模式保护至少缩进到第一个定义(在您的情况下为 add)。

除此之外,由于类型错误,代码仍然无法编译。即 a 不是列表,因此 a == [] 不会进行类型检查。此外,您需要更多括号(用于模式匹配列表和要添加的参数)。

您的意思可能是这样的:

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

编辑:
顺便说一句,我猜你真的想做以下事情:

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

如果是这样的话,你甚至可以写: addNums = zipWith (+) (虽然有点不同,因为它不会抛出当第二个列表比第一个列表短时,模式匹配异常)

The indentation error arises, because you need to indent the pattern guards in the where-clause at least as far as the first definition (add in your case).

Besides that, the code still doesn't compile, because of type errors. I.e a isn't a list, so a == [] doesn't typecheck. Additionally, you need more parenthesis (for pattern matching the list and for the argument to add).

Did you maybe mean something like this:

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

Edit:
By the way, I guess you really want to do the following:

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

If that's the case, you could even write: addNums = zipWith (+) (although it's a little different, since it doesn't throw a pattern match exception, when the second list is short than the first)

飘逸的'云 2024-12-08 05:32:21

第二个问题不是空格问题,您必须将复杂的模式 a:asb:bs 括起来,这样您就可以编写 add res (a: as) (b:bs)

用另一种方式表达有关空白的观点,它在 where 子句中的外观就是它在顶层的外观。你会写:

addNums1 key num = add [] key num

add res (a:as) (b:bs)
  | as == [] = res
  | otherwise = add (res ++ [a+b]) as bs

所以,添加缩进,你会写

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

但是我们不能取消你的 where 子句的缩进,所以它会在左边距。 (我将其修改为等效的内容)

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

因为守卫位于 add 的左侧;在这里,它们实际上位于左边距。我建议将从属定义与控制 where 对齐:

woof xs = foldr moo baaaah xs
  where
  moo :: Integer -> Integer -> Integer
  moo x 0 = 17
  moo x y = x * x + y * (y + x + 1)
  baaaah :: Integer
  baaaah = 3

-- *Main> woof [1,2]
-- 529

它不像某些东西那么可爱,但不太容易出错,因为它减少了更多地思考缩进的认知负担。 (奥列格做到了!)它也会立即避免这个困难。我认为它并不适合任何地方,但这更有吸引力,也许可以使缩进问题更清晰:

 woof xs = foldr moo baaaah xs where
   moo :: Integer -> Integer -> Integer
   moo x 0 = 17
   moo x y = x * x + y * (y + x + 1)
   baaaah :: Integer
   baaaah = 3

然后我们可以看到 where 子句中的定义列表就像 Haskell 模块中的定义列表一样,用 ' 排列左边距”。

The second problem is not a whitespace problem, you have to bracket the complex patterns a:as and b:bs so you'd write add res (a:as) (b:bs)

To put the point about whitespace in another way, the way it looks in the where clause is the way it would look at the top level. You would write:

addNums1 key num = add [] key num

add res (a:as) (b:bs)
  | as == [] = res
  | otherwise = add (res ++ [a+b]) as bs

So, adding indentation, you'd write

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

But we can't unindent your where clause so it would be on the left margin. (I modify it to something equivalent)

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

since the guards are to the left of add; here they actually wind up on the left margin. I recommend lining up subordinate definitions with the governing where:

woof xs = foldr moo baaaah xs
  where
  moo :: Integer -> Integer -> Integer
  moo x 0 = 17
  moo x y = x * x + y * (y + x + 1)
  baaaah :: Integer
  baaaah = 3

-- *Main> woof [1,2]
-- 529

It's not as lovely as some things, but less error prone since it decreases the cognitive load of thinking more about indentation. (And Oleg does it!) It would immediately have averted this difficulty too. I think it isn't suitable everywhere, but this is more attractive and maybe makes indentation questions clearer:

 woof xs = foldr moo baaaah xs where
   moo :: Integer -> Integer -> Integer
   moo x 0 = 17
   moo x y = x * x + y * (y + x + 1)
   baaaah :: Integer
   baaaah = 3

Then we can see that the list of definitions in the where clause are like the list of definitions in a Haskell module, lined up with a 'left margin'.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文