I need to make a palindrome checker using recursion in Haskell for a homework assignment. The function should take in a string and return a Bool. When attempting to compile, I get the error, "Couldn't match type ‘Bool’ with ‘[Char]’."
I'm very new to Haskell, so I'm sure I'm just overlooking something silly, but I figured I'd ask for some help anyway. I've pasted my code below, as well as the full error I'm receiving.
isPalindrome :: String -> Bool
isPalindrome s
| isPalindrome ((null s) || (length s == 1)) = True
| isPalindrome ((s !! 0) /= (s !! (length s - 1))) = False
| otherwise = isPalindrome (tail (init s))
My implementation checks to see if the input string is either empty or of size one, and returns true if it is. If it is not, it checks to see if the first character and last character are different, and if they are, returns false. Otherwise, it calls itself again, passing in the string with the first and last characters cut off.
main.hs:15:19: error:
• Couldn't match type ‘Bool’ with ‘[Char]’
Expected type: String
Actual type: Bool
• In the first argument of ‘isPalindrome’, namely
‘((null s) || (length s == 1))’
In the expression: isPalindrome ((null s) || (length s == 1))
In a stmt of a pattern guard for
an equation for ‘isPalindrome’:
isPalindrome ((null s) || (length s == 1))
|
15 | | isPalindrome ((null s) || (length s == 1)) = True
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
main.hs:16:19: error:
• Couldn't match type ‘Bool’ with ‘[Char]’
Expected type: String
Actual type: Bool
• In the first argument of ‘isPalindrome’, namely
‘((s !! 0) /= (s !! (length s - 1)))’
In the expression: isPalindrome ((s !! 0) /= (s !! (length s - 1)))
In a stmt of a pattern guard for
an equation for ‘isPalindrome’:
isPalindrome ((s !! 0) /= (s !! (length s - 1)))
|
16 | | isPalindrome ((s !! 0) /= (s !! (length s - 1))) = False
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
f xis a function call to the functionfwith the argumentx. But you don't need to call that function, if the test expressionxis already all that you need:isPalindrome :: String -> BoolmeansisPalindrom's first argument is expected to be aString. But what is really meant to be there is a Boolean value, used as a guard, to select the appropriate course of action. Hence the error message. We already have thatBool.The function call in the last line is the recursive call that indeed must be done.
{- ... -}are multiline comments, in Haskell.The usual, more idiomatic Haskell way is to not perform those tests explicitly, but rather arrange for the equivalent pattern matching in the function definition by clauses:
The above code contains some imaginary list patterns in the comments, and their Haskell equivalents in the code itself.
In fact, as @chepner points out in the comments, patterns can often help avoid inefficiency: calculating
lengthis O(n) whereas the pattern matching with[_]is O(1).Of course this specific code is very inefficient still as the other two clauses also perform O(n) operations (
lastandinit). An O(n) algorithm exists.