user11340751
user11340751

Reputation:

Turn a data type into a String for display without `show`

This question has me absolutely puzzled. The goal is to take a specific data type and use it to create a string. The data type is:

data Math = Val Int
           | Add Math Math
           | Sub Math Math
           | Mult Math Math
           | Div Math Math
    deriving Show

This example:

ex1 :: Math
ex1 = Add1 (Val1 2) (Val1 3)

should output "2 + 3" with the correct code.

I wrote the following code and realized I was having two issues:

show :: Math -> String
show (Val n)        = show n
show (Add e1 e2)    = show e1 ++ " + " ++ show e2
show (Sub e1 e2)    = show e1 ++ " - " ++ show e2
show (Mult e1 e2)   = show e1 ++ " * " ++ show e2
show (Div e1 e2)    = show e1 ++ " / " ++ show e2

The curve ball is that the function MUST be named show, as it is - so calling show from Prelude won't work. My first thought it to create a helper that turns every value into a literal but, again, I have no idea how to do that without show for a data type. I legitimately have no idea what direction to head in.

Upvotes: 2

Views: 105

Answers (2)

user11228628
user11228628

Reputation: 1526

You're almost there! To keep show from the Prelude from interfering, add

import Prelude hiding (show)

to the top of your file.

But then, you'll need access to Prelude's show after all, so that you can show the Int inside your Val. So also add this:

import qualified Prelude (show)

With those two lines, you can write:

show :: Math -> String
show (Val n)        = Prelude.show n
show (Add e1 e2)    = show e1 ++ " + " ++ show e2
show (Sub e1 e2)    = show e1 ++ " - " ++ show e2
show (Mult e1 e2)   = show e1 ++ " * " ++ show e2
show (Div e1 e2)    = show e1 ++ " / " ++ show e2

and you should have what you want.


Alternatively, if you want to be implementing Show the class instead of a standalone, identically (and confusingly) named show function, the code you have for show works as-is. You just need to put it inside an instance definition, like this:

instance Show Math where
    show (Val n)        = show n
    -- etc...

Upvotes: 3

chepner
chepner

Reputation: 530833

You can either disable the show method defined by Show:

import Prelude hiding (show)

or you can explicitly refer to show defined in your module. Assuming it is defined in Main,

main = putStrLn $ Main.show (Val 3)

Upvotes: 1

Related Questions