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
".
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With