我写了这段代码:
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行:
模式中的解析错误:添加
答案 0 :(得分:9)
Haskell中的主要压缩规则是,如果要在另一条线上继续定义,则必须进一步缩进而不是您定义的内容。在这种情况下,add
函数的守卫 less 缩进,这就是编译器抱怨的内容。
忽略代码中的其他错误,缩进应该是这样的:
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
,而您的意思是add res (a:as) (b:bs)
。
最后的问题是类型错误。 (:)
运算符的类型为a -> [a] -> [a]
,这意味着它需要元素和列表,并生成列表。在您的代码res:(a+b)
中,您似乎反过来了,因为res
是一个列表,a+b
是元素。由于Haskell中没有运算符将单个元素附加到列表的 end ,因此您必须使用列表并置运算符(++) :: [a] -> [a] -> [a]
代替:res ++ [a+b]
。< / p>
您还要将元素 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
P.S。反复附加到列表的末尾并不是非常有效。事实上,它是O(n 2 )。您可能希望添加到前面,并在完成后反转列表。这是O(n)。
参考文献:
答案 1 :(得分:4)
出现缩进错误,因为您需要至少在第一个定义(在您的情况下为add
)中缩进where子句中的模式保护。
除此之外,由于类型错误,代码仍然无法编译。 I.e 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 (+)
(虽然它有点不同,因为当第二个列表比第一个列表短时,它不会抛出模式匹配异常)
答案 2 :(得分:2)
第二个问题不是空白问题,你必须将复杂模式a:as
和b: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模块中的定义列表类似,排列为“左边距”。