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]
Related
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.
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) )
So I was given the following data type and I had to write a code that checks if an element is in the list (I think I did this one right).
After this I had to declare instance Eq where it would be True if both of my amount lists would be equal. I was supposed to use the element code I wrote earlier.
Could someone tell me what I am doing wrong?
data Amount a = Amount [a]
element [] _ = False
element (x:xs) y = ( x==y) || element xs y
instance Eq (Amount a) where
Amount xs == Amount ys = element xs ys && element ys xs
This is the error message I am receiving
• Couldn't match expected type ‘a’ with actual type ‘[a]’
‘a’ is a rigid type variable bound by
the instance declaration at Probeklausur1.hs:43:10-22
• In the second argument of ‘element’, namely ‘ys’
In the first argument of ‘(&&)’, namely ‘element xs ys’
In the expression: element xs ys && elementS ys xs
• Relevant bindings include
ys :: [a] (bound at Probeklausur1.hs:44:27)
xs :: [a] (bound at Probeklausur1.hs:44:14)
(==) :: Amount a -> Amount a -> Bool
(bound at Probeklausur1.hs:44:17)
|
44 | Amount xs == Amount ys = element xs ys && elementS ys xs | ^^
Probeklausur1.hs:44:49: error:
• Variable not in scope: elementS :: [a] -> [a] -> Bool
• Perhaps you meant ‘element’ (line 40)
|
44 | Amount xs == Amount ys = element xs ys && elementS ys xs | ^^^^^^^^
Let us first analyze the type of element:
element [] _ = False
element (x:xs) y = ( x==y) || element xs y
We see that the first item is a list [a] (based on the [] and (:) data constructors). Furthermore we know that the second item has as type the type of the elements of the list, so a, and since we call x == y, there must be an Eq a constraint. So we derive:
element :: Eq a => [a] -> a -> Bool
A very similar builtin function already exists for this: elem :: Eq a => a -> [a] -> Bool, so it is probably better to use this one instead.
But let us now look at the instance declaration:
instance Eq (Amount a) where
Amount xs == Amount ys = element xs ys && element ys xs
There are two problems here:
we need a to have an Eq type constraint as well, since we need to check if the elements of the list are the same; and
we call element with xs and ys, but both xs and ys have type [a], so this will not work.
We thus first need a mechanism to check that all elements of one list occur in the other list. We can check this with the all :: (a -> Bool) -> [a] -> Bool function:
allElem :: Eq a => [a] -> [a] -> Bool
allElem xs = all (flip elem xs)
So now we can write it like:
instance Eq a => Eq (Amount a) where
Amount xs == Amount ys = allElem xs ys && allElem ys xs
Note that the above might still not be exactly what you want for two reasons:
the order of the two lists is not checked, I assume that this is intentional;
if an element occurs multiple times in the first list, then it does not have to occur that many times in the second list, as long as it occurs at least once we are fine. The length of the two lists can thus be different, and still the two Amounts are considered equal.
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
Background: I'm investigating anonymous recursion, and I'm taking on the challenge of implementing the prelude without using any named recursion just to help it all sit nicely in my mind. I'm not quite there yet, and along the way I've run into something unrelated but still interesting.
map1 = \f -> \x -> if (tail x) == []
then [f (head x)]
else f (head x) : (map1 f (tail x))
map2 f x = if (tail x) == []
then [f (head x)]
else f (head x) : (map2 f (tail x))
map3 f (x:xs) = if xs == [] then [f x] else f x : (map3 f xs)
map4 f (x:[]) = [f x]
map4 f (x:xs) = f x : map4 f xs
GHC complains about the first one, is fine with the second and the third and fourth ones are there just to show how they could be implemented differently.
*Main> map1 (*2) [1..10]
<interactive>:1:15:
No instance for (Num ())
arising from the literal `10'
Possible fix: add an instance declaration for (Num ())
In the expression: 10
In the second argument of `map1', namely `[1 .. 10]'
In the expression: map1 (* 2) [1 .. 10]
*Main> map2 (*2) [1..10]
[2,4,6,8,10,12,14,16,18,20]
*Main> map3 (*2) [1..10]
[2,4,6,8,10,12,14,16,18,20]
*Main> map4 (*2) [1..10]
[2,4,6,8,10,12,14,16,18,20]
If I add a type signature to map1 it's all good.
map1 :: Eq a => (a -> b) -> [a] -> [b]
The first two functions seem pretty much the same to me, so I suppose my question is simply "What's going on here?"
You were bitten by the monomorphism restriction. Anything that is written as foo = ... - meaning that there are no arguments to the definition, and no explicit type is given - has to have a non-generic type according to this restriction. The generic type in this case would, as you said, have had to be Eq a => (a -> b) -> [a] -> [b], but since the monomorphism restriction applies, both a and b are replaced by (), the simplest type that can be inferred for the available type variables.
But, if you use the unconstrained null instead of (== []),
Prelude> let map0 = \f -> \x -> if null (tail x) then [f (head x)] else f (head x) : map0 f (tail x)
Prelude> :t map0
map0 :: (a -> t) -> [a] -> [t]
Prelude> map (*2) [1 .. 10]
[2,4,6,8,10,12,14,16,18,20]
it works without arguments or a signature. Only constrained type variables are subject to the monomorphism restriction.
And if you put the definition of map1 into a file and try to compile it or load it into ghci,
Ambiguous type variable `a0' in the constraint:
(Eq a0) arising from a use of `=='
Possible cause: the monomorphism restriction applied to the following:
map1 :: forall t. (a0 -> t) -> [a0] -> [t] (bound at Maps.hs:3:1)
Probable fix: give these definition(s) an explicit type signature
or use -XNoMonomorphismRestriction
In the expression: (tail x) == []
In the expression:
if (tail x) == [] then
[f (head x)]
else
f (head x) : (map1 f (tail x))
In the expression:
\ x
-> if (tail x) == [] then
[f (head x)]
else
f (head x) : (map1 f (tail x))
ghci only complained in the way it did because it uses ExtendedDefaultRules, otherwise you would have gotten an understandable error message.