[Haskell-cafe] Redefining superclass default methods in a subclass

Brian Hulley brianh at metamilk.com
Thu Jan 4 19:34:00 EST 2007

Roberto Zunino wrote:
> Brian Hulley wrote:
>> because Haskell doesn't allow a superclass (or ancestor class)
>> method default to be redefined in a subclass.
> How one would write instances? Using your Monad class, does
>    instance Monad F where
>       return = ...
>       (>>=) = ...
> automatically define an instance for Applicative?

Yes, but I'd make the method names be "call-site-bound" so the actual method 
that is called is determined by the set of instance decls and class decls 
visible at each particular call site, and any instances that are 
automatically created would be hidden by any explicitly defined instances 
that are visible.

> If it does: What if there already is such an instance? Which one gets
> used for (>>)? The user-defined one or the Monad default?

A possible proposal could be:
1) Class and instance decls would allow method implementations to be given 
for any methods in the class or any ancestor class.

2) Whenever an instance decl is visible there would always be a full set of 
instance decls for all ancestor classes, by supplementing the set of 
explicitly given instance decls that are visible by automatically generated 
implicit instance decls.

3) The most specific method implementation would always be chosen (ie prefer 
an explicit instance method over a class method and prefer a subclass method 
to a superclass method)

In particular rule 2) would mean that the actual method used depends on 
what's available at the call site which means that a Haskell program could 
no longer be thought of as being re-written into a single module before 
compilation, since the meaning of overloaded names would be determined by 
(CalledFromModule, Type) not just Type.

(The desire to hide instance decls or have different instance decls for the 
same type within the same program has come up before on the list but 
unfortunately I can't remember who posted something along these lines or 

> Is separate
> compilation still possible? (If there is no instance right now, one
> might pop out in another module...)

I think it should still be possible because within a module, the 
overloadings would be determined by the set of explicitly defined instances 
in scope in that module. Various optimizations might be more tricky because 
the call site module associated with each overloaded name would need to be 
taken into account when inlining across module boundaries (ie a name used 
inside an inlined function needs to be resolved as if it had been used in 
the module where the function was defined not the module where the function 
is inlined).

For example:

    module A where
    import Proposed.Control.Monad

    data T a = T a
    instance Monad T

    [-# INLINE foo #-}
    foo :: a -> T a
    foo = return      -- uses Monad class default
                            -- which is inherited from the Applicative
                            -- class default

    module B where
    import A
    import Proposed.Control.Monad

    instance Applicative T where
        return x = retB x

    bar :: T a
    bar = return 'q'    -- would use (retB)

    zap :: T a
    zap = foo 'q'    -- would use (return) from A

A question is whether the extra difficulty in resolving overloadings (for 
human reader as well as complier) is worth the advantages of being able to 
get generated definitions for (>>) for Applicative and (fmap) for Functor 
from a single instance decl for (Monad.>>=) etc.

> The class aliases proposal lists several similar shortcomings of the
> current class system.
> http://repetae.net/john/recent/out/classalias.html

IIUC the class alias proposal is about being able to group classes together 
and deal with them as a whole so similar issues of resolving overloadings 
arising from overlapping aliases/ explicit instance decls etc would arise 
(and I imagine the solutions would lie in similar directions).


More information about the Haskell-Cafe mailing list