Implement the
isLengthEven :: [a] -> Bool
function that decides if a list contains an even number of elements. In this exercise, using thelength
function or any other function that returns the number of elements of a list is prohibited. Hint: All we have to check is whether we can walk the entirety of the list through two by two or does the function miss an item at the very end.
For example:
isLengthEven "Apple" == True
,isLengthEven "Even" == True
,isLengthEven [] == False
So far, I tried pattern matching and recursion, which is in my opinion the optimal way of doing this exercise. My code is as follows:
isLengthEven :: [a] -> Bool
isLengthEven [] = False
isLengthEven (x:[]) = False
isLengthEven (x:(y:[])) = True
isLengthEven (x:(y:(z:[]))) = False
isLengthEven (x:(y:(z:(q:[])))) = True
isLengthEven (x:xs) = isLengthEven (xs)
This returns the correct values up until I insert the fifth element into the list. It returns True
for any number of elements above or equal to 5. I suppose there's a problem with the recursion part.
CodePudding user response:
You need only two base cases here:
- an empty list, which has as length
0
and thus should returnTrue
; and - a singleton list which contains one element and thus has an odd length.
The recursive cases each time move two steps forward in the list, so:
isLengthEven :: [a] -> Bool
isLengthEven [] = True
isLengthEven [x] = False
isLengthEven (_:_:xs) = isLengthEven xs
Often one defines two functions: isLengthEven
and isLengthOdd
and thus these functions each time call each other recursively with:
isLengthEven :: [a] -> Bool
isLengthEven [] = True
isLengthEven (_:xs) = isLengthOdd xs
isLengthOdd :: [a] -> Bool
isLengthOdd [] = False
isLengthOdd (_:xs) = isLengthEven xs