用递归判断两个列表长度是否相同

Decide whether two lists are the same in length with recursion

Implement the hasSameLength :: [a] -> [b] -> Bool function that decides whether two lists are the same length. Using the length function is prohibited.

For example: hasSameLength "apple" "peach" == True, hasSameLength "apple" "cherry" == False, hasSameLength [] [1..] == False, hasSameLength [1..] [] == False

到目前为止,我已经试过了

hasSameLength [] [] = True
hasSameLength [] [a] = False
hasSameLength [a] [] = False
hasSameLength (x:xs) (y:ys) = hasSameLength (xs) (ys)

但是如果只有一个参数列表为空,我会收到 non-exhaustive patterns 错误。执行 hasSameLength (x:xs) (y:ys) = hasSameLength (xs) (ys) && hasSameLength (x) (y) 会导致 GHCi 由于某种原因卡在运行时。

hasSameLength [] [] = True
hasSameLength [] _ = False
hasSameLength _ [] = False
hasSameLength (x:xs) (y:ys) = hasSameLength (xs) (ys)

请注意,模式是按从上到下的顺序匹配的。因此,当两个列表都为空时(第一个模式),如果其中一个为空,则它已经是 False。我们不关心另一个列表是否有一个元素或多个元素,我们用下划线表示 _.

在您的代码中,您的模式如下:

hasSameLength [] [a] = False
hasSameLength [a] [] = False

这两行处理一个列表为空而另一个列表只有一个元素的情况。但是当一个为空而另一个有 2 时呢?还是很多?在这种情况下,您会错过该模式并且几乎不可能覆盖它,因为下一个模式:

hasSameLength (x:xs) (y:ys) = hasSameLength (xs) (ys)

也没有涵盖它,因为其中一个列表是空的。

一种对我有帮助的思考方式是:[] [] 作为一个 and 情况,您需要两个参数都为空(或与提供的模式相匹配)用于匹配模式和 _ [] 以及类似的模式,其中一个是 _ 下划线作为 or 的情况,你只需要一个匹配就可以工作。