[Haskell-cafe] Type classes: Missing language feature?

Tillmann Rendel rendel at rbg.informatik.tu-darmstadt.de
Tue Aug 7 11:03:30 EDT 2007


DavidA wrote:
> Now, what I'd like to do is have Lex and Glex, and any further monomial 
> orderings I define later, automatically derive Show and Num instances from 
> Monomial (because it seems like boilerplate to have to define Show and Num 
> instances by hand). Something like the following (not valid Haskell):
> 
> class OrdMonomial m where
>     fromRaw :: Monomial -> m
>     toRaw :: m -> Monomial
> 
> instance OrdMonomial Lex where
>     fromRaw m = Lex m
>     toRaw (Lex m) = m
> 
> instance OrdMonomial Glex where
>     fromRaw m = Glex m
>     toRaw (Glex m) = m
> 
> derive OrdMonomial m => Show m where
>     show m = show (toRaw m)
> 
> derive OrdMonomial m => Num m where
>     m * m' = fromRaw (toRaw m * toRaw m')

Change "derive" to "instance" and enable some GHC extensions by passing

   -fglasgow-exts
   -fallow-overlapping-instances
   -fallow-undecidable-instances

to it (or use a GHC_OPTIONS pragma at the top of your source file) to 
make your code work with GHC. To go a step further, using functional 
dependencies, you can write a small framework:

   -- the class of wrapper types
   class Wrapper w a | w -> a where
     wrap :: a -> w
     unwrap :: w -> a

   -- the class of types with "derived" show instances
   class Wrapper w => DeriveShow w

   -- actual "deriving" of show instances
   instance (Wrapper w a, Show a, DeriveShow w) => Show w where
     show = show . unwrap

and use it for your situation:

   -- the inner type to be wrapped and it's instances
   newtype Monomial = Monomial (Map String Int) deriving (Eq)

   instance Show Monomial where
     show (Monomial a) = ...

   -- some wrappers around this inner type
   newtype Lex = Lex Monomial deriving (Eq)
   newtype Glex = Glex Monomial deriving (Eq)

   instance Wrapper Lex Monomial where
     wrap x = Lex x
     unwrap (Lex x) = x

   instance Wrapper Glex Monomial where
     wrap x = Glex x
     unwrap (Glex x) = x

   -- specialised instances for the wrappers
   instance Ord Lex where
     Lex (Monomial m) <= Lex (Monomial m') = ...

   instance Ord Glex where
     Glex (Monomial m) <= Glex (Monomial m') = ...

   -- "derived" instances for the wrappers
   instance DeriveShow Lex
   instance DeriveShow Glex

But given newtype deriving, wich should work for you for everything 
except Show and Read, this may well be overkill.

   Tillmann


More information about the Haskell-Cafe mailing list