isPalindrome function in Haskell gives an error - haskell

I was trying to write a program that checks whether a list is palindrome and returns Bool.
isPalindrome :: [a] -> Bool
isPalindrome [] = True
isPalindrome [x] = True
isPalindrome xs | (head xs) == (last xs) = isPalindrome (init(tail xs))
| otherwise = False
And I recieved an error message like this:
problem6.hs:4:19: error:
* No instance for (Eq a) arising from a use of `=='
Possible fix:
add (Eq a) to the context of
the type signature for:
isPalindrome :: forall a. [a] -> Bool
* In the expression: (head xs) == (last xs)
In a stmt of a pattern guard for
an equation for `isPalindrome':
(head xs) == (last xs)
In an equation for `isPalindrome':
isPalindrome xs
| (head xs) == (last xs) = isPalindrome (init (tail xs))
| otherwise = False
|
4 | isPalindrome xs | (head xs) == (last xs) = isPalindrome (init(tail xs))
| ^^^^^^^^^^^^^^^^^^^^^^
Failed, no modules loaded.
Because I am not very experienced, I don't understand a thing from error message. So I don't see where the mistake is in my code. Thanks for helping.

The problem is you need to constrain the polymorphic type a. Right now, the compiler has no information about the type, so it can't even know if (==) is defined for a (this is where the No instance for (Eq a) arising from a use of ``==' comes from. It is trying to infer an instance of Eq for a, but it is unable to. You need to help it along).
You should make the type:
isPalindrome :: (Eq a) => [a] -> Bool
Now you're telling it that isPalindrome can only be given lists of things that are instances of Eq.
It points out this piece because your are trying to compare two a's for equality:
(head xs) == (last xs)
A little bit about the error message:
Possible fix:
add (Eq a) to the context of
the type signature for:
isPalindrome :: forall a. [a] -> Bool
The stuff before the => in my suggestion is called the context, and it is where you can add constraints to your types. The suggestion here is telling you to do exactly what I said above (albeit in a much more verbose way).

import Data.List
isPalindrome :: (Eq a) => [a] -> Bool
isPalindrome [] = True
isPalindrome [x] = True
isPalindrome xs
| (head xs /= head (reverse xs)) = False
| otherwise = isPalindrome ( tail (init xs) )

Related

Beginner Type Errors using Filter

I'm just starting to use Haskell, and I'm having what most of you reading would probably consider a beginner blunder.
Consider a list of tuples myTupleList = [(3,6),(4,8),(1,3)]
Nice. I wrote this function to return the list of tuples in which the second element in the first tuple, is double the first element:
(Ex using myTupleList: double myTupleList , which returns [(3,6),(4,8)] )
double [] = []
double (x:xs)
|(snd x) == 2 * (fst x) = x: double xs
|otherwise = double xs
Now I'm sure this isn't the prettiest function in the world, but it works. The problem now is adapting it to use filter. This is my current attempt:
double [] = []
double xs = filter ((2 * (fst(head xs))) == (snd(head xs))) xs
To my undestanding, filter recieves two arguments: a boolean expression and a list. However, I'm getting the following error:
Couldn't match expected type ‘(a, a) -> Bool’
with actual type ‘Bool’
• Possible cause: ‘(==)’ is applied to too many arguments
In the first argument of ‘filter’, namely
‘((2 * (fst (head xs))) == (snd (head xs)))’
In the expression:
filter ((2 * (fst (head xs))) == (snd (head xs))) xs
In an equation for ‘double’:
double xs = filter ((2 * (fst (head xs))) == (snd (head xs))) xs
• Relevant bindings include
xs :: [(a, a)] (bound at Line 9, Column 8)
double :: [(a, a)] -> [(a, a)] (bound at Line 8, Column 1)
I'm sure this is just some silly error or limitation of Haskell as a functional language that I'm not accustomed to or understanding properly, but it would be great to get some help with this.
Thanks
filter expects a function a -> Bool, but (2 * (fst(head xs))) == (snd(head xs)) is not a function that maps an element to a Bool, but simply a Bool. It does not make much sense here to use head x, you use the parameter to get "access" to the element:
double :: (Eq a, Num a) => [(a, a)] -> [(a, a)]
double xs = filter (\x -> 2 * fst x == snd x) xs
You can use pattern matching to unpack the 2-tuple and thus no longer need fst and snd. Furthermore you can perform an η-reduction, and thus remove xs both in the head and the body of double in this case:
double :: (Eq a, Num a) => [(a, a)] -> [(a, a)]
double = filter (\(a, b) -> 2 * a == b)
This gives us:
Prelude> double [(3,6),(4,8),(1,3)]
[(3,6),(4,8)]
We can even make the predicate point-free:
double :: (Eq a, Num a) => [(a, a)] -> [(a, a)]
double = filter (uncurry ((==) . (2 *)))

Creating a safe version of Haskell 'init' function

I'm working my way through "Real World Haskell," and the assignment is to make safe versions of head, tail, last, and init. I've succeeded on the first three, but the Maybe typeclass is killing me on init.
Here is my code:
-- safeInit
safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit (x:xs) = if null xs
then Just [x]
else x : (safeInit xs)
And here are the resultant errors on loading into GHCI (the function starts on line 23 of the original file:
[1 of 1] Compiling Main ( ch04.exercises.hs, interpreted )
> ch04.exercises.hs:27:26: error:
> • Couldn't match expected type ‘Maybe [a]’ with actual type ‘[a]’
> • In the expression: x : (safeInit xs)
> In the expression: if null xs then Just [x] else x : (safeInit xs)
> In an equation for ‘safeInit’:
> safeInit (x : xs) = if null xs then Just [x] else x : (safeInit xs)
> • Relevant bindings include
> xs :: [a] (bound at ch04.exercises.hs:25:13)
> x :: a (bound at ch04.exercises.hs:25:11)
> safeInit :: [a] -> Maybe [a] (bound at ch04.exercises.hs:24:1) | 27 | else x : (safeInit xs) |
> ^^^^^^^^^^^^^^^^^
>
> ch04.exercises.hs:27:31: error:
> • Couldn't match expected type ‘[a]’ with actual type ‘Maybe [a]’
> • In the second argument of ‘(:)’, namely ‘(safeInit xs)’
> In the expression: x : (safeInit xs)
> In the expression: if null xs then Just [x] else x : (safeInit xs)
> • Relevant bindings include
> xs :: [a] (bound at ch04.exercises.hs:25:13)
> x :: a (bound at ch04.exercises.hs:25:11)
> safeInit :: [a] -> Maybe [a] (bound at ch04.exercises.hs:24:1) | 27 | else x : (safeInit xs) |
> ^^^^^^^^^^^ Failed, no modules loaded.
Any way I mark or don't mark either the x or xs on the last two lines with Just, I get different, but very much related, typing errors. What subtlety on using the Maybe type with lists am I missing?
The main reason why this does not work is because your expression x : safeInit xs will not typecheck. Indeed, safeInit xs is a Maybe [a], but (:) has type (:) :: a -> [a] -> [a], so the types do not match.
There is also a semantical error. If null xs is True, then you should return Just [] instead of Just [x], since then x is the last element in the list.
You can make use of fmap :: Functor f => (a -> b) -> f a -> f b (so for f ~ Maybe, fmap is fmap :: (a -> b) -> Maybe a -> Maybe b), to alter a value that is wrapped in a Just:
safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit [_] = Just []
safeInit (x:xs) = fmap (x:) (safeInit xs)
but this will result in a lot of wrapping and unwrapping of values in a Just. It also means that for an infinite list, it will get stuck in an infinite loop. We can simply check if the list contains at least on element, and then perform the init logic as the result of a function we wrap in a Just:
safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit (x:xs) = Just (go xs x)
where go [] _ = []
go (x2:xs) x = x : go xs x2
One interesting problem is how to write safeInit in terms of foldr. Aside from the fun of the puzzle, this allows it to participate in the list fusion optimization in GHC as a "good consumer", which can improve performance in some cases. We start with the first (naive) version in Willem Van Onsem's answer:
safeInit0 :: [a] -> Maybe [a]
safeInit0 [] = Nothing
safeInit0 [_] = Just []
safeInit0 (x:xs) = fmap (x:) (safeInit0 xs)
The first problem with this is that it's not shaped quite like a fold: it has separate cases for [p] and for p:q:rs. A classic trick for patching this up is to pass a Maybe carrying the previous value in the list.
safeInit1 :: [a] -> Maybe [a]
safeInit1 xs0 = go xs0 Nothing
where
-- This first case only happens when
-- the whole list is empty.
go [] Nothing = Nothing
go [] (Just x) = Just [x]
go (x:xs) Nothing = go xs (Just x)
go (x:xs) (Just prev) = (prev:) <$> go xs (Just x)
The next problem is semantic: it doesn't work right with infinite or partially defined arguments. We want
safeInit [1..] = Just [1..]
but safeInit1 will diverge in this case, because fmap is necessarily strict in its Maybe argument. But it turns out there's a bit of information we can use: fmap will only be applied to a Just value in this case. Exercise: prove that.
We'll take advantage of that by representing Maybe [a] in a weird way as (Bool, [a]), where Nothing is represented as (False, []) and Just xs is represented as (True, xs). Now we can be lazier:
safeInit2 :: [a] -> Maybe [a]
safeInit2 xs = case helper2 xs of
(False, _) -> Nothing
(True, xs) -> Just xs
helper2 :: [a] -> (Bool, [a])
helper2 xs0 = go xs0 Nothing
where
go [] Nothing = (False, [])
go [] _ = (True, [])
go (x:xs) mb = case mb of
Nothing -> (True, rest)
Just p -> (True, p:rest)
where
rest = snd (go xs (Just x))
Now this has precisely the shape of a fold:
safeInit3 :: [a] -> Maybe [a]
safeInit3 xs = case helper3 xs of
(False, _) -> Nothing
(True, xs) -> Just xs
helper3 :: [a] -> (Bool, [a])
helper3 xs0 = foldr go stop x0 Nothing
where
stop Nothing = (False, [])
stop _ = (True, [])
go x r mb = case mb of
Nothing -> (True, rest)
Just p -> (True, p:rest)
where
rest = snd (r (Just x))
You might worry that all these intermediate Maybes and pairs will cause performance problems, but in fact GHC is able to optimize them all away, producing something very much like Willem Van Onsem's optimized implementation.

Compiler cannot decide the type of the return value of `take` function

I'm trying to solve the 99 problems in Haskell, and for the 4th question, I have first tried such a solution
myLength :: [a] -> Int
myLength [] = 0
myLength ys = go 1 ys
where
go :: Int -> [a] -> Int
go n xs
| ( (take n xs) == (take (n+1) xs) ) = n
| otherwise = go (n+1) xs
However, the compiler gives the error:
Problem4.hs:10:8: error:
• No instance for (Eq a1) arising from a use of ‘==’
Possible fix:
add (Eq a1) to the context of
the type signature for:
go :: forall a1. Int -> [a1] -> Int
• In the expression: ((take n xs) == (take (n + 1) xs))
In a stmt of a pattern guard for
an equation for ‘go’:
((take n xs) == (take (n + 1) xs))
In an equation for ‘go’:
go n xs
| ((take n xs) == (take (n + 1) xs)) = n
| otherwise = go (n + 1) xs
|
10 | | ( (take n xs) == (take (n+1) xs) ) = n
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
As far as I understood, the reason for the error it that when we try to compare the lists returned from (take n xs) and (take (n+1) xs), the compiler does not know the types of lists in advance, so it cannot compare them, and this is why it complains, so before this line, I need to tell the compiler that both return values are the same type, and the type is [a], but how can we do that ?
A confusion: when we specify the type signature of go, we are explicitly fixing the what is the type of xs, i.e so shouldn't the list that is return by the function take have the same type, namely [a], hence shouldn't the compiler be able to compare them ?
Edit:
Note that, I have another function in the definition of a function, and there are lots of things that are different from the question that is marked as duplicate, and as you can observe, the given answer to that question does not fully solves this question.
What you need is instance contexts (here Eq a), which is indicated by =>:
myLength :: Eq a => [a] -> Int
myLength [] = 0
myLength ys = go 1 ys
where
go :: Eq a => Int -> [a] -> Int
go n xs
| ( (take n xs) == (take (n+1) xs) ) = n
| otherwise = go (n+1) xs
But this is not a proper answer to the question #4, because it adds an additional constraint to the function.
EDIT: For the question "Shouldn't every list be equality comparable?":
Lists are comparable iff their elements are comparable. For example, functions, Kleisli arrows, WrappedArrows are not equality comparable, so aren't lists of them.
{-# Language ScopedTypeVariables #-}
myLength :: forall a. Eq a => [a] -> Int
myLength [] = 0
myLength ys = go 1 ys
where
go :: Int -> [a] -> Int
go n xs
| take n xs == take (n+1) xs = n
| otherwise = go (n+1) xs

Homework: Comparing intermediate expressions with == in Haskell

I have written the code below to test whether a list is a Palindrome or not. To my surprise its not compiling with the error "No instance for (Eq a) arising from a use of == ....". My assumption is that the compiler does not know that leftHalf and rightHalf are lists.
isPalindrome :: [a] -> Bool
isPalindrome [] = False
isPalindrome xs = if (leftHalf == reverse rightHalf)
then True
else False
where leftHalf = take center xs
rightHalf = drop center xs
center = if even (length xs)
then (length xs) `div` 2
else ((length xs) - 1) `div` 2
1) How do I tell the compiler that leftHalf and rightHalf are lists?
2) How would I use pattern matching or other haskell language features to solve this?
EDIT: Thank you all for your input. Special mention to Matt Fenwick for the documentation link and Duri for the elegant tip. I will write the final solutions below just in case
isPalindrome' :: (Eq a) => [a] -> Bool
isPalindrome' [] = False
isPalindrome' xs = if p then True else False
where p = leftHalf == rightHalf
leftHalf = take c xs
rightHalf = take c (reverse xs)
c = div l 2
l = length xs
isPalindrome' can be improved like Demi pointed out
isPalindrome'' :: (Eq a) => [a] -> Bool
isPalindrome'' [] = False
isPalindrome'' xs = if (reverse xs) == xs then True else False
In order to test if two lists are equal, it must be possible to test if the items in the list are equal. Therefore, your list of type [a] must ensure that a is an instance of Eq.
Also, as a matter of style:
x = if c then True else False
can be replaced with
x = c
Check out the Eq typeclass:
ghci> :i (==)
class Eq a where
(==) :: a -> a -> Bool
...
-- Defined in GHC.Classes
infix 4 ==
What you need is a type constraint on isPalindrome.
Also, this code
if (leftHalf == reverse rightHalf)
then True
else False
is unnecessarily long.
You should change your type to:
isPalindrome :: Eq a => [a] -> Bool
And this is really extraneous to find center, it's enough to just write xs == reverse xs - when you computing length xs you go through all the list and there is no economy.

Could not deduce (Eq a) from the context (...)

I'm new to Haskell. I wrote this code:
deleteDuplicates :: [a] -> [a]
deleteDuplicates [] = []
deleteDuplicates (x:xs)
| x == (head xs) = x : (deleteDuplicates (tail xs))
| otherwise = x : (head xs) : (deleteDuplicates (tail xs))
What does this error mean and why did it occur? Am I accidentally comparing two different types somehow?
set2.hs:10:3:
Could not deduce (Eq a) from the context ()
arising from a use of `==' at set2.hs:10:3-16
Possible fix:
add (Eq a) to the context of
the type signature for `deleteDuplicates'
In the expression: x == (head xs)
In a stmt of a pattern guard for
the definition of `deleteDuplicates':
x == (head xs)
In the definition of `deleteDuplicates':
deleteDuplicates (x : xs)
| x == (head xs) = x : (deleteDuplicates (tail xs))
| otherwise = x : (head xs) : (deleteDuplicates (tail xs))
Your type signature is wrong:
deleteDuplicates :: [a] -> [a]
That says your function can work on lists of any type, a, but that isn't true! You later call:
x == (head xs)
So you must be able to compare your type for equality. Meaning the signature must be:
deleteDuplicates :: Eq a => [a] -> [a]
At times like this it's good to remove your explicit type signature, load the function in GHCi and discover what type the interpreter thinks it should have (via :t deleteDuplicates).
More Bugs
Additionally, your use of head there is a bad idea. head is a partial function and will fail when xs == []. I suggest you expand the pattern match:
deleteDuplicates (x1:x2:xs)
| x1 == x2 = ...
| otherwise = x1 : deleteDuplicates (x2:xs)
Also notice the fix to the otherwise case. You were skipping over x2, but what if x2 matched the next element in the list? Something like [1,2,2,3] would have discovered 1 /= 2 and then the recursion would have gotten the list [2,3] - oops!
The compiler is telling you that from the type signature alone it can't work out if a is an instanceof Eq.
deleteDuplicates :: Eq a => [a] -> [a]
You need to tell the compiler that a is an instance of the Eq type class by mentioning it in the signature.
The expression
x == (head xs)
requires == to be defined on the members of xs, which means a must be an instance of the typeclass Eq. Change your function's type signature to
deleteDuplicates :: Eq a => [a] -> [a]

Resources