views:

285

answers:

2

Hi

Basically I've made a polymorphic tree data type and I need a way of counting the number of elements in a given tree. Here's the declaration for my Tree data type:

data Tree a = Empty
| Leaf a
| Node (Tree a) a (Tree a)
deriving (Eq, Ord, Show)

So I can define a tree of Ints like this:

t :: Tree Int
t = Node (Leaf 5) 7 (Node (Leaf 2) 3 (Leaf 7))

However, I need a function to count the number of elements in one of these lists. I've defined this recursive function but I get the error "inferred type is not general enough":

size :: Tree a -> Int
size Empty   = 0
size (Leaf n)    = 1
size (Node x y z)    = size x + size y + size z

Is there something here I shouldn't be doing?

Thanks

Ben

+5  A: 

Look at you last clause: Looking at the left hand side, at Node x y z, what is the type of y? Does size y make sense?

MtnViewMark
+8  A: 

I think it's just a typo when you write

size (Node x y z) = size x + size y + size z

which should just be

size (Node x y z) = size x + size z + 1

since y is no subtree but just the element stored.

Or to make it even clearer

size (Node left elem right) = size left + size right + 1

Technically, your error occurs because the term size y does only make sense if y is again a tree whose size can be computed. Therefore the type of this clause would be inferred to Tree (Tree a) -> Int, which is, compared with the actual Tree a -> Int, not general enough.

Dario
Wouldn't it be `size x + 1 + size z`? Since he is counting the elements and each node contains one element.
BaroqueBobcat
@BaroqueBobcat: Argh ... Yep ;)
Dario
Actually the type of `size` as written would be the infinite type `Tree (Tree (Tree ... ))) -> Int`. In cases such as these a good trick is always to leave out the offending type signature and let the compiler tell you what it thinks should be the right type. In this case, GHC tells me then that it's trying to construct an infinite type...
yatima2975
@yatima2975: Well of course, but as I stated, "the type of this clause would be inferred", which is enough to explain the case.
Dario