Reputation: 5556
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...)
Upvotes: 15
Views: 25200
Reputation: 62808
Here's a minor hint: By writing
instance Show (Leaf a) where
show (Leaf a) = ???
what you actually did was define an empty Show
instance, followed by a top-level show
function. This is why you get the "ambiguous show
" error; you've defined a new show
function, whose name clashes with the existing one.
What you meant to say was
instance Show (Leaf a) where
show (Leaf a) = ???
Note how the second line is indented now. This means you're redefining the existing show
method, as you presumably intended.
Upvotes: 9
Reputation: 376
Your data-type is a perfect candidate for deriving Show
.
data Tree a b = Branch b (Tree a b) (Tree a b) | Leaf a deriving Show
That will automatically generate the Show instance for you.
If you want to create a manual instance of Show, here's the thought process.
First, the basic skeleton:
instance Show (Tree a b) where
-- show :: Tree a b -> String
show (Branch b ltree rtree) = {- some string -}
show (Leaf a) = {- some string -}
Now we know that we'll need some way to show values of type a
and b
as strings. Of course, that means we need to be able to call show
on them directly, so a
and b
must have instances of Show. Here's how that's done:
instance (Show a, Show b) => Show (Tree a b) where
-- show :: Tree a b -> String
show (Branch b ltree rtree) = {- some string -}
show (Leaf a) = {- some string -}
Then it's just filling in the blanks with appropriate strings, such as:
instance (Show a, Show b) => Show (Tree a b) where
-- show :: Tree a b -> String
show (Branch b ltree rtree) = "(( " ++ show ltree ++ " ) <-- ( " ++ b ++ " ) --> ( " ++ show rtree ++ " ))"
show (Leaf a) = "L " ++ show a
Upvotes: 3
Reputation: 8266
The easiest answer would be to automatically derive a Show
instance:
data Tree a b = Branch b (Tree a b) (Tree a b) | Leaf a deriving Show
But let's say that doesn't give you output of the form you want. If you want to define your own Show
instance, you'd do something like:
instance (Show a, Show b) => Show (Tree a b) where
show (Leaf a) = "Leaf " ++ (show a)
show (Branch b l r) = "Branch " ++ (show b) ++ " { " ++ l ++ ", " ++ r " }"
The way you might read that first line is, "given a
and b
are both instances of the Show
typeclass, Tree a b
is also an instance of the Show
typeclass..."
By the way, indentation is important. It may have gotten mangled in the snippet you pasted, but you must indent the show
function definitions under the instance
declaration.
Upvotes: 9
Reputation: 27549
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
a
s and b
s. That's what the (Show a, Show b) =>
part does, it specifies the preconditions you require for your instance to work.
Upvotes: 25