
On Wed, Dec 12, 2012 at 05:20:06PM +0000, Henning Thielemann wrote:
On Wed, 12 Dec 2012, Ross Paterson wrote:
On Sun, Dec 09, 2012 at 01:24:36AM +0000, Ross Paterson wrote:
A more economical variation on this idea would be to lift these classes to functors, e.g.
class ShowF f where showsPrecF :: Show a => Int -> f a -> ShowS
instance (ShowF m, Show e, Show a) => Show (EitherT e m a) where showsPrec d (EitherT m) = showParen (d > 10) $ showString "EitherT " . showsPrecF 11 m
instance (ShowF m, Show e) => ShowF (EitherT e m) where showsPrecF = showsPrec
To also lift Prelude classes like Show to Compose (which seems desirable), we'd need to use an explicit dictionary instead:
class ShowF f where showsPrecF :: (Int -> a -> ShowS) -> Int -> f a -> ShowS
instance (ShowF f, ShowF g) => ShowF (Compose f g) where showsPrecF sp d (Compose x) = showParen (d > 10) $ showString "Compose " . showsPrecF (showsPrecF sp) 11 x
instance (ShowF f, ShowF g, Show a) => Show (Compose f g a) where showsPrec = showsPrecF showsPrec
If you tolerate a (Functor f) constraint you may use a helper type, that lifts (ShowF f, Show a) to (Show (f a)):
class ShowF f where showsPrecF :: (Show a) => Int -> f a -> ShowS
newtype Inner g a = Inner (g a)
instance (ShowF g, Show a) => Show (Inner g a) where showsPrec p (Inner g) = showsPrecF p g
instance (Functor f, ShowF f, ShowF g) => ShowF (Compose f g) where showsPrecF d (Compose x) = showParen (d > 10) $ showString "Compose " . showsPrecF 11 (fmap Inner x)
instance (Functor f, ShowF f, ShowF g, Show a) => Show (Compose f g a) where showsPrec = showsPrecF
Doing an fmap just to make an instance work is pretty unpleasant, but having to hand-write all the instances, as the explicit dictionary version would require, is probably worse.
You may also make Functor a superclass of ShowF.
I'm not sure about that -- one might want to make Set an instance. Assuming we have Eq1, Ord1, Show1 and Read1, what would be a good name for the module defining them?