type error when compiling - haskell

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.

Related

Debugging type Errors in Haskell

I'm trying to write a function, returning all permutations from a list in Haskell:
perms :: [a] -> [[a]]
perms [] = [[]]
perms xs = map (\y -> concat_each y (perms (list_without y xs))) xs
list_without :: (Eq a) => a -> [a] -> [a]
list_without x xs =
filter (\y -> not (y==x)) xs
concat_each :: a -> [[a]] -> [[a]]
concat_each x xs =
map (\y -> x:y) xs
What I think happens in line3:
y is a and x is [a], so
list_without y xs is [a].
perms (list_without ...) is thus [[a]]
so concat_each y (perms ...) gets a and [[a]], resulting in [[a]]
So the function for map is a -> [[a]] and everything should be okay.
But the compiler seems to see things differently:
Couldn't match type `a' with `[a]'
`a' is a rigid type variable bound by
the type signature for perms :: [a] -> [[a]]
at C:\Users\Philipp\Desktop\permutations.hs:1:10
Expected type: [a]
Actual type: [[a]]
Relevant bindings include
y :: a (bound at permutations.hs:3:18)
xs :: [a] (bound at permutations.hs:3:7)
perms :: [a] -> [[a]]
(bound at permutations.hs:2:1)
In the expression: concat_each y (perms (list_without y xs))
In the first argument of `map', namely
`(\ y -> concat_each y (perms (list_without y xs)))'
How would I debug this error message properly? I don't really know where to start checking my types.
map :: (x -> y) -> [x] -> [y]
The first argument you gave to map has type a -> [[a]], i.e., x = a and y = [[a]] so
:: [x] -> [ y ]
map (\y -> ...) :: [a] -> [[[a]]]
-- ^ ^^^^^
-- x = a, y = [[a]]
In this case, the result of that map (\y -> ...) xs is a list where each element corresponds to the permutations starting with a fixed element y in xs. In the end, you don't care which element a permutation starts with; you can forget that separation using concat:
perms = concat (map (\y -> ...) xs)
-- or
perms = concatMap (\y -> ...) xs
-- or
perms = xs >>= \y -> ...

Haskell: General type of function pushing element to a list

Given a general function
cons x xs = x:xs
How would one give it a general type? I tried doing
cons:: a -> [b] -> [c]
But it does not seem to work
A list is defined as (pseudocode):
data [a] = [] | a : [a]
Therefore a list can only contain elements of the same type: either it is an empty list ([]) so it does not contain any elements, or it is a CONS (:) and then the head is of type a and so is its tail [a].
Therefore if you define:
cons x xs = x : xs
Haskell takes a look at the signature of the constructor: a : [a]. So it derives that x is an a, xs is an [a], and (x:xs) is an [a] as well (the head of the data statement).
As a result, the most general type signature of cons is:
cons :: a -> [a] -> [a]
cons x xs = x : xs
You cannot define a cons with x :: a and xs :: [b] (with a different from b) since in that case you invoke the constructor (:) :: a -> [a] -> [a] with conflicting types.
In Haskell, you usually do not have to write type signatures. If you omit them, Haskell will fill in the most generic one. You can use :t in the ghci interactive shell to obtain the type of a function. Like:
Prelude> let cons x xs = x : xs
Prelude> :t cons
cons :: a -> [a] -> [a]
Finally note you do not need to define a cons function, you can simply use (:):
cons :: a -> [a] -> [a]
cons = (:)
Remember, a and b are potentially different types, and here you want to be able to add an a to the list. So, you want both lists to be type [a].
cons :: a -> [a] -> [a]
cons = (:)

[[Int]] -> [Int] with multiply

I try to learn Haskell and I don't know how to create a function which takes a list of lists and multiplies each element in this list e.g.
[[2,3], [8,3,2], [2,10,1], [2,2,2,2]] -> [6,48,20,16]
I try something like this but it doesn't work. If anyone knows how to do this will be really helpfully for me:
listOfProductInt :: [[Int]] -> [Int]
listOfProductInt [] = []
listOfProductInt lists = foldl (\y x-> multipleInts x concat) [] lists
multipleInts :: (Num a) => [a] -> a
multipleInts list1 = foldl (\y x -> y * x) 1 list1
Very simple really, you need map:
map product [[2,3],[8,3,2],[2,10,1],[2,2,2,2]]
The product function multiplies all elements in a list. It is included in the Prelude, which is imported by default. In other words, it is normally available.
The map function applies that function to each element in the list.
If you prefer a solution with folds only, first a couple of rules of thumb:
Never use foldl (“lazy† left fold”), except in very specific circumstances (which you won't encounter until you've long learned the subtleties).
Use foldr (lazy right fold) for deconstructing lists, if the result is lazy. In particular, this is usually the right choice if your fold produces a list again: foldr will only consume the list by demand, and it doesn't keep a reference to the original head, hence it works smoothly even on infinite lists and avoids memory blowup (in fact, the garbage collector can reclaim parts of the list that are already processed, before the processing is finished!)
Use foldl' (strict left fold) for “atomic” operations like computing the sum of all values in a list.
So let's start with
listOfProductInt :: [[Int]] -> [Int]
-- listOfProductInt [] = [] -- no need for that, folds already handle the empty case.
listOfProductInt lists = foldr _ [] lists
multipleInts :: (Num a) => [a] -> a
multipleInts list1 = foldl' _ 1 list1
GHC will inform you
/tmp/wtmpf-file9164.hs:4:32:
Found hole ‘_’ with type: [Int] -> [Int] -> [Int]
Relevant bindings include
lists :: [[Int]] (bound at /tmp/wtmpf-file9164.hs:4:18)
listOfProductInt :: [[Int]] -> [Int]
(bound at /tmp/wtmpf-file9164.hs:4:1)
In the first argument of ‘foldr’, namely ‘_’
Unfortunately this is not as informtive as usually because both the result and the individual sub-lists have type [Int]. I'll annotate the type:
[Int] -- the sublist we're focusing on
-> [Int] -- the result of the future product-computations yet to be done
-> [Int] -- the result at this point of the computation
Now, for handling the sublist that's on the agenda first, we have multipleInts. So, it should look something like
listOfProductInt lists = foldr (\l -> _ (multipleInts l)) [] lists
to which GHC replies
/tmp/wtmpf-file9164.hs:4:39:
Found hole ‘_’ with type: Int -> [Int] -> [Int]
Relevant bindings include
l :: [Int] (bound at /tmp/wtmpf-file9164.hs:4:34)
lists :: [[Int]] (bound at /tmp/wtmpf-file9164.hs:4:18)
listOfProductInt :: [[Int]] -> [Int]
(bound at /tmp/wtmpf-file9164.hs:4:1)
In the expression: _
In the expression: _ (multipleInts l)
In the first argument of ‘foldr’, namely
‘(\ l -> _ (multipleInts l))’
You may recognise Int -> [Int] -> [Int], or generally a -> [a] -> [a], as the signature of the cons-operator (:), and that's what's needed here:
listOfProductInt lists = foldr (\l -> (:) (multipleInts l)) [] lists
or, using point-free composition,
listOfProductInt = foldr ((:) . multipleInts) []
Proceed with the implementation of multipleInts:
/tmp/wtmpf-file9164.hs:7:29:
Found hole ‘_’ with type: a -> a -> a
Where: ‘a’ is a rigid type variable bound by
the type signature for multipleInts :: Num a => [a] -> a
at /tmp/wtmpf-file9164.hs:6:17
Relevant bindings include
list1 :: [a] (bound at /tmp/wtmpf-file9164.hs:7:14)
Well, a -> a -> a where a fulfills a Num constraint? That's just the simple product operation!
multipleInts list1 = foldl' (*) 1 list1
†foldl is only lazy in the values, but not in the spine. In practice, this tends to give you the worst of both worlds: the processor is immediately clogged with having to handle the whole list, but instead of actually doing useful computations, it merely builds up stacks of memory-hogging laziness-thunks.

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]].

rigid type variable error in 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

Resources