-1
data BinTree el = EmptyBinTree
                | NonEmptyTree (BinTree el) el (BinTree el)
                  deriving (Show)

 binTreeFold :: (acc -> el -> acc -> acc) -> acc -> BinTree el -> acc
 binTreeFold _ acc EmptyBinTree = acc
 binTreeFold f acc (NonEmptyTree l n r) = f (binTreeFold f acc l) n (binTreeFold f acc r)

I'm having trouble implementing a function using binTreeFold that returns a list with the leaves the tree contains. I've tried something like this:

leaves' :: BinTree a -> [a]
leaves' t = binTreeFold (\EmptyBinTree n EmptyBinTree -> n) [] t

but that doesn't work - I get this error:

Couldn't match expected type `[a]' with actual type `BinTree t0'
    In the pattern: EmptyBinTree
    In the first argument of `binTreeFold', namely
      `(\ EmptyBinTree n EmptyBinTree -> n)'
    In the expression:
      binTreeFold (\ EmptyBinTree n EmptyBinTree -> n) [] t

I have already written a version of leaves:

leaves :: BinTree a -> [a]
leaves EmptyBinTree = []
leaves (NonEmptyTree (EmptyBinTree) n (EmptyBinTree)) = [n]
leaves (NonEmptyTree l n r) = leaves l ++ leaves r

but for our homework we have to rewrite it using binTreeFold.

leaves' :: BinTree a -> [a]
leaves' t@(NonEmptyTree (EmptyBinTree) n (EmptyBinTree)) = binTreeFold (\l n r -> [n]) [] t 
leaves' t@(NonEmptyTree l n r) = leaves' l ++ leaves' r 

I have something like this now, but I'm not sure if that's what I'm supposed to do, because it's almost identical to the first function.

user3742929
  • 360
  • 3
  • 17
  • You can express leaves directly as a `binTreeFold` without pattern matching on the tree directly at all, so that's probably what's expected. – Ganesh Sittampalam Jun 16 '14 at 06:11

1 Answers1

1

Your current attempt has a few problems.

The type error you're getting points to the main one: you wrote a pattern EmptyBinTree of type BinTree t0, but the function passed to binTreeFold should take something of type acc as its first and third arguments.

Since you passed [] as the acc value in the second argument to binTreeFold, the acc type must also be [a], i.e. a list of something.

You also shouldn't be trying to pattern-match for specific values directly in the lambda arguments of the function you pass to binTreeFold - just give the lists a name so that you can use them in the body of the function and pattern-match on them there if necessary. Otherwise the function will fail on inputs not covered by your patterns.

You also need to work out what the correct result value for the function is, bearing in mind that it also needs to be of type acc.

So change your function to something like (\xs n ys -> ...) (you fill in the ...) and see how that goes.

Ganesh Sittampalam
  • 28,821
  • 4
  • 79
  • 98
  • I've already tried a lot like this :). I also wrote other functions using the binTreeFold, but I really don't know what I have to do here to get the leaves of the tree, since i only want the n when xs and ys are EmptyBinTrees. – user3742929 Jun 16 '14 at 05:45
  • The point is that `xs` and `ys` are not trees, but the lists you have already calculated from the trees. Consider what these elements will look like in the cases where there was an empty tree on either side and where there wasn't, and do a case analysis inside the body of the function. – Ganesh Sittampalam Jun 16 '14 at 06:06
  • leaves' t = binTreeFold (\[] n [] -> [n]) [] t I have this now, but it gives me an error: Non-exhaustive patterns in lambda. How can i specify different cases in the lambda function? – user3742929 Jun 16 '14 at 10:39
  • You can't specify different cases directly, use variable names and use `case` inside the body. – Ganesh Sittampalam Jun 16 '14 at 10:57
  • Could you help me with that? I'm relatively new to Haskell and haven't heard of case in our lectures, google couldn't help me really either. – user3742929 Jun 16 '14 at 11:02