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

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 [])]

Related

Couldn't match expected type `Int' with actual type `a'

import Data.List
data Tree a = Leaf a | Node (Tree a) a (Tree a) deriving Show
toTree :: Ord a => [a] -> Tree a
toTree xs = Node (balancedTree (take n xs')) (xs'!!n) (balancedTree (drop n xs'))
where
xs' = sort xs
n = middle xs
middle :: Num a => [a] -> a
middle xs = fromIntegral ((length xs `div` 2) + 1)
balancedTree :: Ord a => [a] -> Tree a
balancedTree (x:[]) = Leaf x
balancedTree xs = Node (balancedTree (take n xs')) (xs'!!n) (balancedTree (drop n xs'))
where
xs' = sort xs
n = middle xs
This is my code for converting from a list to a binary tree. I know there are many mistakes but I just want to get the types errors sorted before I start debugging. I get the following errors in both the "toTree" method and the "balancedTree" method as they are both really the same and will be condensed into one when the errors are sorted out.
ex7.hs:6:38: error:
* Couldn't match expected type `Int' with actual type `a'
`a' is a rigid type variable bound by
the type signature for:
toTree :: forall a. Ord a => [a] -> Tree a
at ex7.hs:5:1-32
* In the first argument of `take', namely `n'
In the first argument of `balancedTree', namely `(take n xs')'
In the first argument of `Node', namely
`(balancedTree (take n xs'))'
* Relevant bindings include
xs' :: [a] (bound at ex7.hs:8:9)
n :: a (bound at ex7.hs:9:9)
xs :: [a] (bound at ex7.hs:6:8)
toTree :: [a] -> Tree a (bound at ex7.hs:6:1)
|
6 | toTree xs = Node (balancedTree (take n xs')) (xs'!!n) (balancedTree (drop n xs'))
| ^
I have tried for hours to fix it by searching stackOverflow but I can't figure it out. The type declaration of "toTree" must stay the same. Also the definition of Tree should stay the same.
My understanding is that "take" required an "Int" and I am giving it an "a". I do not know how I can fix this.
The problem is that middle returns an a, not an Int. Indeed:
middle :: Num a => [a] -> a
middle xs = fromIntegral ((length xs `div` 2) + 1)
But in your balancedTree, you use it as if it is an index, and take n, drop n, and !! n require n to be an Int, indeed:
balancedTree :: Ord a => [a] -> Tree a
balancedTree (x:[]) = Leaf x
balancedTree xs = Node (balancedTree (take n xs')) (xs'!!n) (balancedTree (drop n xs'))
where
xs' = sort xs
n = middle xs
The type signature does not make much sense either. You can calculate the length over any list, not only from lists that consist out of numbers. You thus should construct a function that returns the index in the middle of the list and use that. For example:
middle :: [a] -> Int
middle = (length xs `div` 2) + 1
That being said, using length, etc. is usually not a good idea in Haskell. length requires O(n) time, and furthermore for infinite lists, it will get stuck in an infinite loop. Often if you use functions like length, there is a more elegant solution.
Instead of using a "top-down" approach, it might be better to look at a "bottom-up" approach, where you iterate over the items, and on the fly construct Leafs, and group these together in Nodes until you reach the top.

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

Converting a foldl into fold1

I am using the following fold to get the final monotonically decreasing sequence of a list.
foldl (\acc x -> if x<=(last acc) then acc ++ [x] else [x]) [(-1)] a
So [9,5,3,6,2,1] would return [6,2,1]
However, with foldl I needed to supply a start for the fold namely [(-1)]. I was trying to turn into to a foldl1 to be able to handle any range of integers as well as any Ord a like so:
foldl1 (\acc x -> if x<=(last acc) then acc ++ [x] else [x]) a
But I get there error:
cannot construct infinite type: a ~ [a]
in the second argument of (<=) namely last acc
I was under the impression that foldl1 was basically :
foldl (function) [head a] a
But I guess this isn't so? How would you go about making this fold generic for any Ord type?
I was under the impression that foldl1 was basically :
foldl (function) [head a] a
No, foldl1 is basically:
foldl function (head a) (tail a)
So the initial element is not a list of head a, but head a.
How would you go about making this fold generic for any Ord type?
Well a quick fix is:
foldl (\acc x -> if x<=(last acc) then acc ++ [x] else [x]) [head a] (tail a)
But there are still two problems:
in case a is an empty list, this function will error (while you probably want to return the empty list); and
the code is not terribly efficient since both last and (++) run in O(n).
The first problem can easily be addressed by using pattern matching to prevent that scenario. But for the latter you better would for instance use a reverse approach. Like for instance:
f :: Ord t => [t] -> [t]
f [] = [] -- case when the empty list is given
f a = reverse $ foldl (\acc#(ac:_) x -> if x <= ac then (x:acc) else [x]) [head a] (tail a)
Furthermore personally I am not a huge fan of if-then-else in functional programming, you can for instance define a helper function like:
f :: Ord t => [t] -> [t]
f [] = [] -- case when the empty list is given
f a = reverse $ foldl g [head a] (tail a)
where g acc#(ac:_) x | x <= ac = (x:acc)
| otherwise = [x]
Now reverse runs in O(n) but this is done only once. Furthermore the (:) construction runs in O(1) so all the actions in g run in O(1) (well given the comparison of course works efficient, etc.) making the algorithm itself O(n).
For your sample input it gives:
*Main> f [9,5,3,6,2,1]
[6,2,1]
The type of foldl1 is:
Foldable t => (a -> a -> a) -> t a -> a
Your function argument,
\acc x -> if x<=(last acc) then acc ++ [x] else [x]
has type:
(Ord a) => [a] -> a -> [a]
When Haskell's typechecker tries typechecking your function, it'll try unifying the type a -> a -> a (the type of the first argument of foldl1) with the type [a] -> a -> [a] (the type of your function).
To unify these types would require unifying a with [a], which would lead to the infinite type a ~ [a] ~ [[a]] ~ [[[a]]]... and so on.
The reason this works while using foldl is that the type of foldl is:
Foldable t => (b -> a -> b) -> b -> t a -> b
So [a] gets unified with b and a gets unified with the other a, leading to no problem at all.
foldl1 is limited in that it can only take functions which deal with only one type, or, in other terms, the accumulator needs to be the same type as the input list (for instance, when folding a list of Ints, foldl1 can only return an Int, while foldl can use arbitrary accumulators. So you can't do this using foldl1).
With regards to making this generic for all Ord values, one possible solution is to make a new typeclass for values which state their own "least-bound" value, which would then be used by your function. You can't make this function as it is generic on all Ord values because not all Ord values have sequence least bounds you can use.
class LowerBounded a where
lowerBound :: a
instance LowerBounded Int where
lowerBound = -1
finalDecreasingSequence :: (Ord a, LowerBounded a) => [a] -> [a]
finalDecreasingSequence = foldl buildSequence lowerBound
where buildSequence acc x
| x <= (last acc) = acc ++ [x]
| otherwise = [x]
You might also want to read a bit about how Haskell does its type inference, as it helps a lot in figuring out errors like the one you got.

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