Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write customised show function in Haskell

Tags:

enums

haskell

I am defining a Octave type:

data Octave = 1 | 2 | 3
  deriving (Show, Read, Ord, Enum)

Since '1' is not valid for data constructor identifiers, I have to do it like so:

data Octave = O1 | O2 | O3
  deriving (Show, Eq, Read, Ord, Enum)

Now, if I show Octave O1 it shows "O1" which is not exactly what I want. I want the result to be "1". I know we can customise our Show behaviour like this:

instance Show Blabla where                                                                                       
  show (Blabla ints chars list num) =                                                                            
    "integers = " ++ show ints ++ "\n"

But the problem is that I am using enumeration type which means it doesn't have a value except its identifier name 'O1'. How can I access that in Haskell?

Another question: How can I read it back?

read "O1" :: Octave works, but I want read "1" :: Octave

instance Read Octave where
  read "1" = O1
  read "2" = O2
  read "3" = O3

This doesn't work: "read is not a (visible) method of class Read".

like image 803
yehe Avatar asked Dec 01 '22 18:12

yehe


2 Answers

Taking advantage of Octave's Enum instance and using the Show and Read instances for Int we can implement showing and reading like this:

data Octave = O1 | O2 | O3 deriving (Eq, Ord, Enum)

instance Show Octave where
    show o = show (fromEnum o + 1)

instance Read Octave where
    readsPrec prec = map (\(n,s) -> (toEnum (n - 1), s)) . readsPrec prec

I.e. fromEnum and toEnum convert between octaves and ints so that O1 <-> 0 and O2 <-> 1, so we have to adjust by one in both reading and writing.

like image 78
shang Avatar answered Dec 24 '22 11:12

shang


Seems like all you need is this, right?

instance Show Octave where
  show O1 = "1"
  show O2 = "2"
  show O3 = "3"

Define show with three clauses, and let the pattern matcher figure it out.

like image 27
amalloy Avatar answered Dec 24 '22 13:12

amalloy