rigid type variable error in Haskell - haskell

Why this gives rigid type variable error:
data MyTree a = Leaf [a]
| Branch (String, a) [MyTree a]
deriving (Show)
list :: MyTree a -> [a]
list (Leaf []) = []
list (Leaf m) = m
list (Branch _ (x:xs)) = list x ++ map (list) xs
-------------------------------------------------------------
Couldn't match type `a' with `[a]'
`a' is a rigid type variable bound by
the type signature for list :: MyTree a -> [a]
at test.hs:6:15
Expected type: MyTree a -> a
Actual type: MyTree a -> [a]
In the first argument of `map', namely `(list)'
In the second argument of `(++)', namely `map (list) xs'
In the expression: list x ++ map (list) xs

The part of the error that actually tells you what is happening is:
Expected type: MyTree a -> a
Actual type: MyTree a -> [a]
In the first argument of `map', namely `(list)'
So the type of the function you give to map is wrong. But why is it so? map has type:
map :: (a -> b) -> [a] -> [b]
list is MyTree a -> [a], and therefore:
map list :: (MyTree a -> [a]) -> [MyTree a] -> [[a]]
That means map list xs will have type [[a]]. You are using it like this:
list x ++ map list xs -- omitting unnecessary parentheses.
(++) is list concatenation; it expects two lists of the same type. list x, however, is [a] instead of [[a]], which leads to the type error. Since [a] is the type of an element of [[a]], you might try using (:), instead of (++), to prepend list x to the rest of your list-of-lists.
list (Branch _ (x:xs)) = list x : map list xs
That, however, is redundant: you are applying the same list function to x and the elements of xs. That means you can simplify it to:
list (Branch _ xs) = map list xs
We are still not done, as map list xs has type [[a]], and you want [a]. That is easy to solve, though: just use concatMap, which maps the function and flattens the resulting list-of-lists. The full definition would then become:
list :: MyTree a -> [a]
list (Leaf m) = m
list (Branch _ xs) = concatMap list xs
I have removed the redundant (Leaf []) case. Note that your function did not cover the (
Branch _ []) case; that's not a problem now that we are not matching (x:xs) only.

The type of map (list) xs is [[a]] and you want something of type [a]. There is a function concat that we can use: concat (map list xs), but we can write it more idiomatically with concatMap: concatMap list xs

Related

How can I use generic type annotations to describe a recursive data type?

Here's the function:
comboGraph :: [a] -> Int -> [b]
comboGraph _ 0 = []
comboGraph [] _ = []
comboGraph (x:xs) n =
(buildEdges x xs) : comboGraph xs n
where buildEdges h t = (h, comboGraph t (n-1))
Ths function takes in a list of type a, a number, and returns a list of type b. As you can see, though, type b is actually a recursive type -- it will be something along the lines of [(a, [(a, b1)])]. When I try to compile, I get this error:
• Couldn't match type ‘b’ with ‘(a, [b0])’
‘b’ is a rigid type variable bound by
the type signature for:
comboGraph :: forall a b. [a] -> Int -> [(a, [b])]
at xxx.hs:15:15
Expected type: [(a, [b])]
Actual type: [(a, [(a, [b0])])]
• In the expression: (buildEdges x xs) : comboGraph xs n
In an equation for ‘comboGraph’:
comboGraph (x : xs) n
= (buildEdges x xs) : comboGraph xs n
where
buildEdges h t = (h, comboGraph t (n - 1))
How do I properly annotate this function?
To make the issue a bit more evident, let's substitute the definition of buildEdges in the final case of your definition:
comboGraph (x:xs) n =
(x, comboGraph xs (n-1)) : comboGraph xs n
The result of comboGraph is supposed to be a list, but one whose elements are pairs that also have a comboGraph result (i.e. a list of the same type) within. As the type error you got says, that doesn't work -- it's as if you wanted a list with two tails. The fix is switching to a different data structure that reflects what you are trying to do:
-- Feel free to substitute better names.
data Combo a = Empty | Node a (Combo a) (Combo a)
deriving (Eq, Ord, Show)
Empty covers the base cases which used to result in an empty list, while Node has one appropriately-typed field for each of the things you want to combine in the recursive case. comboGraph then becomes:
comboGraph :: [a] -> Int -> Combo a
comboGraph _ 0 = Empty
comboGraph [] _ = Empty
comboGraph (x:xs) n = Node x (comboGraph xs (n-1)) (comboGraph xs n)
(Note that Combo is actually a binary tree with values on the nodes.)
I like the other answer, and I think you should use it. But it makes some reasoning leaps that require some intuition, and it can be hard to get this intuition without doing things the mechanical way a few times. So in this answer, I will show how to start with a failing definition like the one you have, "turn a crank", and mechanically get a solution that does work. The technique below can be applied to any infinite type error.
You have the following clause (paraphrased slightly):
comboGraph (x:xs) n =
(x, comboGraph xs (n-1)) : {- ... -}
Just doing some straightforward type inference reasoning, we can see that comboGraph takes a list of some type (from the fact that it pattern matches on x:xs) and a number (from the fact that it subtracts one). Let's pick a concrete (monomorphic! but not yet known) type a for the list elements and see what we can infer about what it returns.
Well, it clearly returns a list with tuples inside. And the first part of the tuple is just an a. What about the second part? The second part of the tuple is... whatever type comboGraph returns. So comboGraph returns a type t satisfying the equation:
t = [(a, t)]
The only solution to this equation is [(a, [(a, [(a, [(a, ...)])])])]. Such infinite types don't exist raw in Haskell. But there is a standard trick to get quite close: use (type-level) recursion by introducing a newtype. We're solving for t, but Haskell types have to start with an upper-case letter, so we'll name our solution to this equation T.
newtype T a = T [(a, T a)] deriving Show
Now we don't quite have T a ~ [(a, T a)], but we do have an isomorphism: namely, \(T xs) -> xs :: T a -> [(a, T a)] and T :: [(a, T a)] -> T a are inverses. So now we can write your comboGraph definition by exploiting this isomorphism. Let's name the other half of the isomorphism:
unT :: T a -> [(a, T a)]
unT (T xs) = xs
So:
comboGraph (x:xs) n =
T ((x, comboGraph xs (n-1)) : unT (comboGraph xs n))
The base cases have to get wrapped in T, as well, of course:
comboGraph _ 0 = T []
comboGraph [] _ = T []
Try it in ghci:
> comboGraph "abc" 3
T [('a',T [('b',T [('c',T [])]),('c',T [])]),('b',T [('c',T [])]),('c',T [])]

Haskell add to list in list

i have the following code
groupEq :: Eq a => [a] -> [[a]]
groupEq list = foldl (\acc x -> if (isType acc x) then ((last acc) ++ [x]) else acc++[[x]]) [] list
isType :: Eq a => [[a]] -> a -> Bool
isType list item
| (length list) == 0 = False
| head (last list) == item = True
| otherwise = False
Now, i am having difficulties understanding why it would not compile.
The problem is with the ((last acc) ++ [x]) part of it. I understand it as it takes the last element of accumulator, which would be [[a]] at this point and tries to add an element to it.
The idea what i want to achieve is this:
-- groupEq [1,2,2,3,3,3,4,1,1] ==> [[1], [2,2], [3,3,3], [4], [1,1]]
Full error is
Couldn't match type ‘a’ with ‘[a]’
‘a’ is a rigid type variable bound by
the type signature for groupEq :: Eq a => [a] -> [[a]]
at exam_revisited.hs:3:12
Expected type: [[[a]]]
Actual type: [[a]]
Relevant bindings include
x :: a (bound at exam_revisited.hs:4:28)
acc :: [[a]] (bound at exam_revisited.hs:4:24)
list :: [a] (bound at exam_revisited.hs:4:9)
groupEq :: [a] -> [[a]] (bound at exam_revisited.hs:4:1)
In the first argument of ‘last’, namely ‘acc’
In the first argument of ‘(++)’, namely ‘(last acc)’
What am i missing here?
groupEq is declared to return [[a]], but ((last acc) ++ [x]) is of type [a].
A quick and dirty solution is to change this expression into
init acc ++ [last acc ++ [x]].

haskell Either String (NestedList a)- why doesn't it work

I am trying to append function that works on Nested Lists like regular lists. I want to use Either String (Nested a) so that it returns error or the appended list. But it keeps failing. I am not doing NestedList[NestedList a] anywhere. Why does it say it expected [NestedList (NestedList a)]
module Main where
data NestedList a=Elem a | List[NestedList a] deriving Show
flatten ::NestedList a->[a]
flatten (Elem x)=[x]
flatten (List(x:xs))=flatten(x)++flatten(List xs)
--flatten NestedList (x:xs)=flatten(x)++flatten(xs)
flatten(List [])=[]
------------------
count::[a]->Int
count a=length (a)
-----------------
append::NestedList a->NestedList a->Either String (NestedList a)
append (_) (Elem a)=Left "Elements are not allowed"
append (Elem a) (_)=Left "Elements are not allowed"
append (List a) (List b)=Right (List (flatten(List a)++flatten(List b)))
-------------------
main=do
print(flatten (List[Elem 1, Elem 2,List[Elem 1, Elem 2 ]]))
print(count(flatten (List[Elem 1, Elem 2,List[Elem 1, Elem 2 ]])))
print(append (List[List[Elem 1, Elem 2 ]]) (List[Elem 1, Elem 2,List[Elem 1, Elem 2 ]] ))
gives me this error
flatten_list.hs:18:52:
Couldn't match type `a' with `NestedList a'
`a' is a rigid type variable bound by
the type signature for
append :: NestedList a
-> NestedList a -> Either String (NestedList a)
at flatten_list.hs:15:9
Expected type: [NestedList (NestedList a)]
Actual type: [NestedList a]
In the first argument of `List', namely `a'
In the first argument of `flatten', namely `(List a)'
In the first argument of `(++)', namely `flatten (List a)'
flatten_list.hs:18:69:
Couldn't match type `a' with `NestedList a'
`a' is a rigid type variable bound by
the type signature for
append :: NestedList a
-> NestedList a -> Either String (NestedList a)
at flatten_list.hs:15:9
Expected type: [NestedList (NestedList a)]
Actual type: [NestedList a]
In the first argument of `List', namely `b'
In the first argument of `flatten', namely `(List b)'
In the second argument of `(++)', namely `flatten (List b)'
import Data.Traversable
append :: NestedList a -> NestedList a -> Either String (NestedList a)
append (Elem x) (Elem y) = Right $ List [Elem x, Elem y]
append (Elem _) _ = Left ""
append _ (Elem _) = Left ""
append (List xs) (List ys) = fmap List $ sequenceA $ zipWith append xs ys
The append you wrote in your questions seems to want to just flatten and concatenate the two lists, which is rather pointless, since you are throwing away all the structure. If this is desired behavior, then just use a regular list:
append' :: NestedList a -> NestedList a -> Either String [a]
append' (Elem x) (Elem y) = Right $ [x,y]
append' (Elem _) _ = Left ""
append' _ (Elem _) = Left ""
append' a b = Right $ flatten a ++ flatten b
You could also define your datatype in terms of the free monad:
import Control.Monad.Free
type NestedList = Free []
flatten :: NestedList a -> [a]
flatten = retract
append :: NestedList a -> NestedList a -> Either String (NestedList a)
append (Pure x) (Pure y) = Right $ Free [Pure x, Pure y]
append (Pure _) _ = Left ""
append _ (Pure _) = Left ""
append (Free xs) (Free ys) = fmap Free $ sequenceA $ zipWith append xs ys
This definition is isomorphic to the one you gave.

type error when compiling

I don't understand why the following code won't compile:
append :: [a] -> [a] -> [a]
append xs ys = foldr (:) ys xs
traverse :: a -> [a] -> [[a]]
traverse x [] = [[x]]
traverse x (y:ys) = append [(x:y:ys)] (map (y:) (traverse x ys))
comb :: [a] -> [[a]]
comb [] = [[]]
comb (x:[]) = [[x]]
comb (x:y:[]) = [[x,y],[y,x]]
comb (x:xs) = map (traverse x) (comb xs)
It produces the following error:
pr27.hs:13:20:
Couldn't match type `a' with `[a]'
`a' is a rigid type variable bound by
the type signature for comb :: [a] -> [[a]] at pr27.hs:10:1
Expected type: [a] -> [a]
Actual type: [a] -> [[a]]
In the return type of a call of `traverse'
In the first argument of `map', namely `(traverse x)'
Failed, modules loaded: none
But when I load just traverse and use it in an expression similar to the above, I get the desired result. What's going on?
Main> map (traverse 3) [[1,2],[2,1]]
[[[3,1,2],[1,3,2],[1,2,3]],[[3,2,1],[2,3,1],[2,1,3]]]
The problem is that comb has to return a value of type [[a]]. traverse returns a value of type [[a]], so mapping it over another list produces [[[a]]], which has too many levels of nesting.
Let's look at map. It has a type map :: (x -> y) -> [x] -> [y]. traverse x has a type [a] -> [[a]]. Now we need to combine the two. To do this, we replace x with [a] and y with [[a]], getting ([a] -> [[a]]) -> [[a]] -> [[[a]]]. This clearly shows the result of mapping traverse has to have at least three levels of nesting.
If you look at your example, this is what you actually get. For comb, you only want one two levels deep.
The reason your example worked in GHCi is because an expression there can have any type. Your map (traverse 3) [[1,2], [2,1]] expression is perfectly legal; however, it has the type Num a => [[[a]]], which is a list of lists of lists of numbers. (Try it: :t map (traverse 3) [[1,2], [2,3]].) However, the type of comb is [a] -> [[a]]. This means the result has to be a list of lists, not a list of lists of lists. So the issue is that map (traverse 3) is incompatible with comb, not that it is illegal by itself.

haskell - yet another infinite type error

I am trying to solve problem 10 from the ninety nine haskell problems.
Here is my solution that I believe is correct.
The pack function (from question 9) is already correct. The problem is with the encode function.
pack :: (Eq a) => [a] -> [[a]]
pack [] = []
pack (x:xs) = (x : takeWhile (== x) xs) : (pack $ dropWhile (== x) xs)
encode :: (Eq a) => [a] -> [(Int, a)]
encode [] = []
encode list = (encode' $ head packed) : (encode $ tail packed)
where packed = pack list
encode' l = (length l, head l)
When I load the file from ghci, this is the error:
encode.hs:6:0:
Occurs check: cannot construct the infinite type: a = [a]
When generalising the type(s) for `encode'
Line 6 is the line containing encode [] = []
What's wrong with my encode function? I keep checking the types of the variables used and I believe there is nothing wrong.
Function usage example (assuming code is working correctly):
pack "aaaabbbbccccccddddddd"
> ["aaaa","bbbb","cccccc","ddddddd"]
encode "aaaabbbbccccccddddddd"
> [(4,'a'),(4,'b'),(6,'c'),(7,'d')]
Recursion is somewhat clumsy here. It's much better to use a higher-order function.
You already have a function encode' :: [a] -> (Int, a) that encodes one sub-list, and you want to encode all of them. Applying a function to every element of a list is a very common pattern which is encapsulated by the higher-order function map :: (a -> b) -> [a] -> [b].
Taking advantage of map, we can simply write:
encode :: (Eq a) => [a] -> [(Int, a)]
encode list = map encode' $ pack list
where encode' xs = (length xs, head xs)
You can also avoid the helper function by using a list comprehension:
encode :: (Eq a) => [a] -> [(Int, a)]
encode list = [(length xs, head xs) | xs <- pack list]
In general, try to use existing higher-order functions where appropriate instead of doing your own recursion. It's both more readable and less prone to mistakes.
encode $ tail packed
We have
packed :: [[a]]
tail packed :: [[a]]
But we need to pass an [a] to encode.
(Think about it like this: list needs to go through pack. packed is the output from pack, but in the recursive call it will be passed to pack again.)
Your problem is that the function encode expects "unpacked" lists, but you pass a "packed" list.
Adding type signatures helps a lot here, I added a type signature for encode'
{-# LANGUAGE ScopedTypeVariables #-}
pack :: (Eq a) => [a] -> [[a]]
pack [] = []
pack (x:xs) = (x : takeWhile (== x) xs) : (pack $ dropWhile (== x) xs)
encode :: forall a. (Eq a) => [a] -> [(Int, a)]
encode [] = []
encode list = (encode' $ head packed) : (encode $ tail packed)
where packed = pack list
encode' :: [a] -> (Int, a)
encode' l = (length l, head l)
and the compiler finds the error quickly:
[1 of 1] Compiling Main ( test.hs, interpreted )
test.hs:9:42:
Couldn't match type `a' with `[a]'
`a' is a rigid type variable bound by
the type signature for encode :: Eq a => [a] -> [(Int, a)]
at test.hs:8:1
Expected type: [(Int, a)]
Actual type: [(Int, [a])]
In the second argument of `(:)', namely `(encode $ tail packed)'
In the expression: (encode' $ head packed) : (encode $ tail packed)
Failed, modules loaded: none.
Because that would only work if a was the same as [a] and therefore the same as [[a]] etc. That's an infinite type error. Or simply the difference between a "packed" list ([[a]]) and a "unpacked" list ([a]) in your sample.
(For better understanding: "packed" list is a list after applying the pack function ;-) )
edit: fixed ScopedTypeVariables vs. ExistentialQuantification error, thanks John L
You can do pattern matching on the result to pack, instead of using head and tail.
Then it looks like this:
encode :: (Eq a) => [a] -> [(Int, a)]
encode [] = []
encode list = encode' x : encode xs
where (x:xs) = pack list
encode' l = (length l, head l)
The type error comes from xs is of type [[a]] because pack
returns [[a]], but encode expects an [a] argument.
I agree with #hammar that higher-order functions are a great way to handle this problem.
Here's a general explanation of what happened, though:
Every time I've had an infinite type error, it's had the following form:
I've had a function which called itself, but called itself with a "deeper"* type than it had been passed.
Let's make a simple infinite type error:
*Main> let f (_:xs) = f [xs]
<interactive>:1:19:
Occurs check: cannot construct the infinite type: t0 = [t0]
And let's break down why: the type of f can't be determined: If f :: [a] -> [[a]], then the f [xs] :: [[a]] -> [[[a]]], which gets passed to the original f, which can't return [[[a]]].
*My definition of "deeper":
[[a]] is "deeper" than [a]
Constructor (Constructor a) is "deeper" than Constructor a

Resources