Making a data type an instance of Show in Haskell

norman picture norman · Sep 21, 2012 · Viewed 15.2k times · Source

I need to make the following data type an instance of Show:

data Tree a b = Branch b (Tree a b) (Tree a b) | Leaf a 

I'm fairly new at this, but to start with, I interpreted this declaration as

"We have made a new type called Tree, which is parameterized with types a and b. A tree can be one of two things: a Branch which holds a piece of data of type b, plus two more Trees, or a Leaf which holds a data item of type a."

Now, I need to make a way to "Show" it nicely (nested branches, etc.), without using deriving. So far, I have only been writing functions in a module Main and loading/playing with them in an interpreter window, so I haven't actually done things with constructors, etc, before. Nevertheless, I figured I could just start off by declaring the tree data type within my file, as shown at the beginning of the question, and go from there.

As I messed around with "Show" without much success, I thought maybe I needed to define a small component of the tree and how to "Show" it first, before trying to work with the whole tree:

data Leaf a = Leaf a

instance Show (Leaf a) where
show (Leaf a) = ??? 

I tried a number of things in the ??? spot, such as "a", just a by itself, putStrLn, etc., but none are printing out the value of a when I say something like

>show (Leaf 3)

In fact, I have in many cases encountered this, which probably means I am not locating things right:

Ambiguous occurrence `show'
    It could refer to either `Main.show', defined at a2.hs:125:1
                          or `Prelude.show',
                             imported from `Prelude' at a2.hs:2:8-11
                             (and originally defined in `GHC.Show')

...which I addressed by calling "Main.show," which of course doesn't work.

I guess the question is, where do I go with all this...or maybe just, "How can I fix the Leaf "Show" utility so that I can figure out how to extend it?" (assuming I have to define it first...)

Answer

Daniel picture Daniel · Sep 21, 2012

You have to start like that:

data Tree a b = Branch b (Tree a b) (Tree a b) | Leaf a

instance (Show a, Show b) => Show (Tree a b) where
    show (Leaf x) = show x
    show (Branch p l r) = ???

In order to show a Tree a b you have to first be able to show as and bs. That's what the (Show a, Show b) => part does, it specifies the preconditions you require for your instance to work.