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
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to