Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to "show" a constructor in lower case

Tags:

haskell

show

Suppose I'd want to create a new data type and make the constructors showable, only in lower case instead of their upper case definition. For example:

data Day = Monday | Tuesday | Wednesday| Thursday | Friday | Saturday | Sunday

By adding deriving Show, ghci would print them as "Monday, Tuesday.. etc." To get it to show "monday, tuesday.. etc" I've tried to make a special instance of show:

import Data.Char

strToLower :: [Char] -> [Char]
strToLower (x:xs) = toLower x : strToLower xs
strToLower [] = []

instance Show Day where
   show d = strToLower (show d)

where the first occurrence of show should designate my new amended show function (which will be called everytime I print) whereas for the second I intend the normally derived version of show, to get from the constructor name to a String.

Of course this doesn't work (circular definition) as the ghci has no clue to my separate meanings of the word "show" but I can't figure out how to let him know the distinction, for both versions need to be named show, the first because that's what print calls to and the second because it's a predefined haskell function which can give me a String out of a constructor name. I've tried

show d = strToLower ((showsPrec 0 d) "")

but this comes down to the same circular definition, at least that's what I guess from the ghci getting stuck in a loop.

I understand why constructor names need to begin with an upper case letter, but showing them lower case shouldn't be a problem, should it? I know I could just define my show function for every case separately, e.g. show Monday = "monday" show Tuesday = "tuesday" etc, but I'm only using the days of the week as an example here and my real data type consists of 64 constructors so I think it would be more elegant to solve it differently somehow.

Is it possible to dig into the haskell definition of show and alter a copy of that code? This is the only possible solution I can think of but I don't know how to do it, if it is possible at all. Probably not. So other solutions are very welcome as well!

Thank you for taking your time,

Jelle (Haskell beginner)

like image 760
user1734761 Avatar asked Oct 10 '12 13:10

user1734761


1 Answers

You can actually do this using the Typeable and Data classes.

To do this you need the DeriveDataTypeable extension, turn it on with -XDeriveDataTypeable or by putting the following line at the start of the file that defines your type:

{-# LANGUAGE DeriveDataTypeable #-}

You can now import the needed modules:

import Data.Data
import Data.Typeable

And derive Typeable and Data:

data Day = Monday | Tuesday | Wednesday| Thursday | Friday | Saturday | Sunday
     deriving (Typeable, Data)

Now you can use toConstr to get a constructor representation:

instance Show Day where
   show = strToLower . showConstr . toConstr

But see the other answers on whether you'd really want to, instead of simply using a showDay function or your own type class instead.

like image 105
Julien Oster Avatar answered Oct 02 '22 06:10

Julien Oster