[Haskell] PROPOSAL: class aliases
Ross Paterson
ross at soi.city.ac.uk
Thu Oct 27 07:18:32 EDT 2005
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.
More information about the Haskell
mailing list