atom feed35 messages in org.haskell.haskell[Haskell] PROPOSAL: class aliases
FromSent OnAttachments
John MeachamOct 12, 2005 7:41 pm 
Philippa CowderoyOct 12, 2005 7:55 pm 
John MeachamOct 12, 2005 8:16 pm 
Wolfgang JeltschOct 13, 2005 5:48 am 
John MeachamOct 13, 2005 6:03 am 
Malcolm WallaceOct 13, 2005 6:15 am 
Andres LoehOct 13, 2005 6:23 am 
Malcolm WallaceOct 13, 2005 6:29 am 
John MeachamOct 13, 2005 6:37 am 
John MeachamOct 13, 2005 6:39 am 
Simon Peyton-JonesOct 13, 2005 7:02 am 
Benjamin FranksenOct 13, 2005 7:26 am 
Benjamin FranksenOct 13, 2005 7:33 am 
S.M.KahrsOct 13, 2005 7:37 am 
John MeachamOct 13, 2005 8:32 am 
Simon Peyton-JonesOct 13, 2005 9:23 am 
Udo StenzelOct 13, 2005 9:46 am 
Jan-Willem MaessenOct 13, 2005 9:58 am 
Paul GovereauOct 13, 2005 1:21 pm 
Jacques CaretteOct 13, 2005 1:52 pm 
John MeachamOct 13, 2005 4:45 pm 
John MeachamOct 13, 2005 6:13 pm 
John MeachamOct 13, 2005 6:21 pm 
David MenendezOct 13, 2005 6:49 pm 
John MeachamOct 13, 2005 8:33 pm 
aj...@spamcop.netOct 13, 2005 11:25 pm 
Ashley YakeleyOct 14, 2005 6:20 am 
Ashley YakeleyOct 14, 2005 6:31 am 
Wolfgang JeltschOct 14, 2005 9:46 am 
Wolfgang JeltschOct 14, 2005 11:44 am 
Wolfgang JeltschOct 14, 2005 11:47 am 
Remi TurkOct 14, 2005 2:05 pm 
Udo StenzelOct 15, 2005 6:15 am 
Ross PatersonOct 27, 2005 6:58 am 
Wolfgang JeltschOct 28, 2005 7:05 am 
Subject:[Haskell] PROPOSAL: class aliases
From:Ross Paterson (ro@soi.city.ac.uk)
Date:Oct 27, 2005 6:58:08 am
List:org.haskell.haskell

On Thu, Oct 13, 2005 at 05:51:36AM -0700, John Meacham wrote:

On Thu, Oct 13, 2005 at 12:21:41PM +0100, Simon Peyton-Jones wrote:

Anyway, my main point is: would a smaller change not suffice?

I do not think it suffices.

We could extend the supertyping relationship some more to make it suitable, but I think we will end up with the exact same proposal but with different terminology :)

For concreteness, here's a slight narrowing of Simon's version. Given your H98 classes

class Additive a where (+) :: a -> a -> a zero :: a

class Additive a => Negative where (-) :: a -> a -> a negate :: a -> a

x - y = x + negate y negate x = zero - x

class Multiplicative a where (*) :: a -> a -> a one :: a

extend the class syntax with an annotation on the assumptions (! for now), to allow

class (Show a, !Additive a, !Negative a, !Multiplicative a) => Num a where fromInteger :: Integer -> a

one = fromInteger 1 zero = fromInteger 0

(This is for illustration -- I'm not claiming this is the ideal factoring of the Num class.)

The ! annotations would be ignored during type inference. Their only meaning is

(a) the class declaration for Num may include defaults for the methods of the !'d superclasses,

(b) an instance declaration for Num also defines instances for the !'d superclasses, and thus may include definitions for the methods of Num and those superclasses. Any methods of these classes not defined in the instance are assigned default definitions, with defaults in the Num class overriding any in the superclasses.

Thus if a Num instance is given, a Show instance must also be in scope (as now), but Additive, Negative and Multiplicative instances cannot be given, e.g.:

instance Show Int65536 where showsPrec n = showsPrec n . toInteger

instance Num Int65536 where (+) = primPlusInt65536 (-) = primMinusInt65536 (*) = primMultInt65536 fromInteger = primFromInteger65536

In comparision with the class alias proposal, this loses aliasing, but retains the ability to define defaults for superclasses, which is what I've been missing for ages.

All these proposals need to address repeated inheritance, as in an example from Davis Menendez:

class (!Functor m) => Monad m where { fmap = liftM; ... } class (!Functor d) => Comonad d where { fmap = liftD; ... }

With the above rules, it would be illegal to define instances of both these classes for the same type, but one could define

class (!Monad f, !Comonad f) => MonadComonad f where ...

as long as either the class includes a default definition of fmap, or the instance includes a definition:

instance MonadComonad Id where fmap f (Id x) = Id (f x) ...

MPTCs raise extra issues, like

class (!Functor f, !Functor g) => Something f g where fmap = ...

Which Functor is being given a default fmap? I'd prefer to avoid this by requiring that the !'d assumptions have exactly the same arguments as the class being defined.