[Haskell-cafe] Redefining superclass default methods in a subclass
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
module A where
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
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.
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