Implement the
hasSameLength :: [a] -> [b] -> Bool
function that decides whether two lists are the same length. Using thelength
function is prohibited.
For example:
hasSameLength "apple" "peach" == True
,hasSameLength "apple" "cherry" == False
,hasSameLength [] [1..] == False
,hasSameLength [1..] [] == False
So far, I've tried
hasSameLength [] [] = True
hasSameLength [] [a] = False
hasSameLength [a] [] = False
hasSameLength (x:xs) (y:ys) = hasSameLength (xs) (ys)
But if only one of the parameter lists is empty, I get a non-exhaustive patterns
error. Doing hasSameLength (x:xs) (y:ys) = hasSameLength (xs) (ys) && hasSameLength (x) (y)
results in GHCi getting stuck in runtime for some reason.
CodePudding user response:
hasSameLength [] [] = True
hasSameLength [] _ = False
hasSameLength _ [] = False
hasSameLength (x:xs) (y:ys) = hasSameLength (xs) (ys)
Please note that patterns are matched in order from top to bottom. So when both lists are empty (first pattern), if one of them is empty, it's already a False
. We don't care about whether the other list has one element or many and we indicate that with an underscore _
.
In your code, you have the pattern as follows:
hasSameLength [] [a] = False
hasSameLength [a] [] = False
These 2 lines take care of when one list is empty and the other one has only one element. But what about when one is empty and the other one has 2? Or many? This is the case that you miss with that pattern and it's almost impossible to cover it because the next pattern:
hasSameLength (x:xs) (y:ys) = hasSameLength (xs) (ys)
also doesn't cover it, since one of the lists is empty.
A way of thinking about it that helps me is to look at: [] []
as an and
case where you need both parameters to be empty (or match the provided pattern for that matter) for the pattern to match and _ []
and similar patterns when one of them is an _
underscore as an or
case where you just need one match for it to work.