1

So I'm learning Haskell and I have to implement a treeunzip function that takes a tree of the type (Tree (a,b)) where 'a' and 'b' are integers and returns a list of the two trees unzipped, that is (Tree a, Tree b).

I can get one of the two trees but I can't put them together in a list. What I came up with is this:

treeunzip :: (NewTree) -> (treeunzipL, treeunzipR)

NewTree is defined as:

data NewTree = NewLeaf | NewNode Int Int NewTree NewTree deriving Show

Tree is defined as:

data Tree = Leaf | Node Int Tree Tree deriving Show

Here are the treeunzipL and treeunzipR functions, I don't know if it matters.

treeunzipL :: (NewTree) -> (Tree)
treeunzipL NewLeaf = (Leaf)
treeunzipL (NewNode x y lSubTree rSubTree) = (Node x (treeunzipL (lSubTree)) (treeunzipL (rSubTree)))


treeunzipR :: (NewTree) -> (Tree)
treeunzipR NewLeaf = (Leaf)
treeunzipR (NewNode x y lSubTree rSubTree) = (Node y (treeunzipR (lSubTree)) (treeunzipR (rSubTree)))

Now that obviously gives me an error when loading the module because treeunzip has a signature but not an implementation. Is there any way to get around this?

Thank you.

BourbonCreams
  • 353
  • 4
  • 21
  • 1
    `treeunzipped :: NewTree -> (Tree, Tree)`. The type doesn't care about function names used to implement the function. – chepner Oct 21 '16 at 13:58
  • 1
    Also, you don't need two separate types if you parameterize the original type. `data Tree a = Leaf | Node a (Tree a) (Tree a)`, then `treeunzipped :: Tree (a,b) -> (Tree a, Tree b)`. – chepner Oct 21 '16 at 13:59
  • Ok I think I'm going to study some more theory because all I understood from your comments was that a function only contains data types and not function calls. Not sure what parameterizing means. Thank you though. – BourbonCreams Oct 21 '16 at 14:34

1 Answers1

2

Your problem seems to be that you are trying to imply the definition in the type. The two are separate and must be provided separately. (The compiler can infer a type from a definition, but it cannot infer the definition from the type.)

treeunzip :: NewTree -> (Tree, Tree)
treeunzip t = (treeunzipL t, treeunzipR t)

However, you should parameterize your original type to

data Tree a = Leaf | Node a (Tree a) (Tree a)

so that you only need one treeunzip function:

treeunzip :: Tree (a, b) -> (Tree a, Tree b)
treeunzip Leaf = (Leaf, Leaf)
treeunzip (Node (a, b) left right) = ((Node a left' right'),
                                      (Node b left'' right''))
    where (left', left'') = treeunzip left
          (right', right'')  treeunzip right

> treeunzip (Node (1,2) (Node (3,4) Leaf Leaf) (Node (5,6) Leaf Leaf))
(Node 1 (Node 3 Leaf Leaf) (Node 5 Leaf Leaf),Node 2 (Node 4 Leaf Leaf) (Node 6 Leaf Leaf))
chepner
  • 497,756
  • 71
  • 530
  • 681