Marcin 'Qrczak' Kowalczyk wrote:

> The other issue is efficiency if you want f to behave the same way even
> when the instance Eq (Maybe String) is not visible at f's definition.
> It would mean that every overloaded function must be extended to
> directly receive all dictionaries it needs. This can give not only
> very many, but even an infinite number of dictionaries needed (with
> polymorphic recursion). I cannot imagine a sensible implementation
> of the function:
>     h :: Eq a => a -> a -> Int
>     h x y = if x == y then 0 else 1 + h [x] [y]
> which would make h "1" "2" return 7 if in some other module there is:
>     instance Eq [[[[[[[String]]]]]]] where
>         x == y = length x == length y
>

The example with polymorphic recursion is a nice example.  Now, if the `instance Eq
[[[String]]]' *were* in scope, I can imagine how to implement this.  One way would be 
to
unfold the recursion enough steps to accomodate the overlap.  It wouldn't be pretty, 
but
how often does this come up ;-)

Especially given the above example, I don't think that trying to make overlapping 
behave
consistently, regardless of instance scope, is the right approach.  I think it would be
fine if the compiler complained if my imports lead to inconsistent instance scopes.

>
> > Let us put some concrete example. Suppose the module  G  contains
> >   g :: Eq a => ([a] -> [a]) -> [[a]] -> Int
> >   g            h               (xs:_) =
> >                                     let ... <something complex>
> >                                         l = length $ h xs
> >                                                      ----
> >                                         ys = ...<something complex>
> >                                     in  l+(length ys)
> > g  is compiled straightforward.
>
> So it passes just the Eq a dictionary to h.

Hmm....  `h' here is not overloaded - no parameter of a function can be.  Any 
dictionary
passing necessary would happend where `g' was applied to something.  See previous note.

>
> > > Unless one accepts that subtle differences in contexts, ones
> > > depending on the implementation rather than the interface, change
> > > the meaning. And that definition like "g :: some signature; g = f"
> > > can cause g to be defined on exactly the same types as f, but with
> > > a different meaning. And that the same polymorphic function used on
> > > the same type has different meanings in various places.
> >
> > First, could you provide an example?
> > Maybe, the one constructed from above `f' ...
>
> It depends on what rules do we have. For example if f was required
> to have the type signature:
>     f :: (Eq a, Eq (Maybe a)) => [a] -> [a]
> to see the more specific instances, nevertheless:
>     g :: Eq a => [a] -> [a]
>     g = f
> was allowed, then this is an example. It's bad because it's easier to
> spot an error when it is catched at compile time (this is not allowed)
> than when it leads to a change in behavior (something is allowed but
> this is allowed in a different way and the compiler has picked one of
> them).

Urm... in any consistent set of rules, `g' above would result in a type error.  If `f'
(which, BTW, doesn't need the `Eq a' in its signature) is required to have `Eq (Maybe
a)' in its context, then `g' will as well.  This is independent of the instance scoping
issue, because in order to even see `f', `g' would also see the overlap which forced 
`f'
to have that context.

--Jeff

Reply via email to