Tue, 15 Feb 2000 17:51:51 +0300 (MSK), S.D.Mechveliani <[EMAIL PROTECTED]> pisze:
> Here A is a superclass for B, so, `B a =>' is a more special
> condition than `A a =>'.
I am not brave enough to try to formulate general rules of determining
which context is more general, with all fancy things like repeated type
variables, functional dependences, class and instance contexts, partial
application of types, which would work safely across modules where
not everything is visible at once, and which would be comprehensible
for humans, maintainable in compilers, without penalties for those who
don't use them, without negative impact on future language extensions
and without letting subtle bugs in more complex programs go through
undetected. The issue of classes is complex enough without allowing
overlappings at all...
> > I simply don't accept the situation when adding an instance or
> > declaration changes the meaning of a code that was legal before.
>
> Thus, in the above example, adding instance B a => C a ...
> does not change the real meaning of the code.
It does. Without it
data X = ...
instance A X where ...
instance B X where ...
used some version of implied "instance C X", now it uses another.
And similarly, with classes A,B,C and instances for C as above,
and with
data X = ...
instance A X where ...
it uses one version of implied "instance C X", and adding
instance B X where ...
makes it use another.
> Maybe, overlaps does not change radically the situation. In any
> case, when the compiler sees some operation op of class C in the
> module M, one has to find the instance(s) for C in the modules
> visible from M. The difference is, probably, in that with the
> overlapping instances, the compiler has not right to stop after the
> first found instance.
> Right?
Yes. It's about a difference between proving that something exists
and that it does not.
Well, the compiler has to examine more anyway, because it must ensure
that the program is correct at all, i.e. that the same instance is not
defined twice. It's more about a human ensuring that the meaning of
the code is what he wants, assuming the code is correct (the compiler
accepted it). It's not so dangerous (and basically unavoidable) if
failure to examine the whole program caused an error to be reported
by the compiler, because then I know that I missed something.
> Something hard to understand. I do not see why one has to play
> these strange tricks instead of introducing most natural overlapping
> instances.
Because I don't see how to define the semantics of overlapping
instances in a safe, comprehensible etc. way.
Do you say that the function with the type
f :: Eq a => [a] -> [a]
must get the dictionary of "Eq (Maybe a)", because it internally uses
the equality on "Maybe a" and it might get redefined for a particular
choice of a? What if it is passed to a higher order function: how
could a function of the type
g :: Eq a => ([a] -> [a]) -> [[a]] -> Int
know that it must sometimes pass the "Eq (Maybe a)" dictionary to its
argument when calling it, or on the unbounded set of other possible
types involving a?
Or you say that in the same program different implementations of
"instance Eq (Maybe String)" might be used in various places, because
of subtle differences between contexts in those places?
--
__("< Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/
\__/ GCS/M d- s+:-- a22 C+++$ UL++>++++$ P+++ L++>++++$ E-
^^ W++ N+++ o? K? w(---) O? M- V? PS-- PE++ Y? PGP+ t
QRCZAK 5? X- R tv-- b+>++ DI D- G+ e>++++ h! r--%>++ y-