Marcin 'Qrczak' Kowalczyk  <[EMAIL PROTECTED]>  writes on 15 Feb 2000


>> 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,  [..]

There exist several brave and experienced developers. 
The question is to what extent the braveness expands.
I suspect they foresee the possible obstacles better than I recently 
do.

> with all fancy things like repeated type
> variables, functional dependences, class and instance contexts, 
> [..]
>      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...

Is it complex enough to block out the user from certain natural 
style of setting computation?
As you say, the life is hard. It is hard for the implementor and has
to be easy for the user.


>> > 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.

Merely using another instance does not seem to change the meaning 
of the code. In functional programming, the result matters, not the 
way to compute it. The meaning is the result value. If this instance
disagrees somewhat strongly with the former instance, then yes, it 
changes the code meaning. But the overlap correctness has to be the
automatic consequence of the algorithm setting. This is like in 
example with the matrix determinant. If the programmer really 
understands what and how one computes, then the instances are agreed
automatically.


>> Something hard to understand. I do not see why one has to play
>> these strange tricks instead of introducing most natural overlapping
>> instances.

> 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
t> 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?


I fear, I am loosing the thread. The discussion was on the 
overlapping instances. And this latter question is maybe, on giving 
a polymorphic function to another function as the argument.
I am not an implementor and doubt about `dictionaries', still could we
put it more concretely? Say,

  f :: Eq a => [a] -> [a]
  f xs = ...

  g :: Eq a => ([a] -> [a]) -> [[a]] -> Int
  g h xs = ...

  h1 = g f ["ab","c"]
  h2 = g f [[Just 'a', Just 'b'], [Just 'c']]

Can it be set like this?
Eq (Maybe a)  is, probably, the standard instance derived from Eq a.
What does this mean here `f internally uses the equality on "Maybe a"'
?
Could we put somewhat more concrete or clear question?


------------------
Sergey Mechveliani
[EMAIL PROTECTED]



Reply via email to