To my reply

>> I join this suggestion.
>> ..
>> ad hoc polymorphism is still very desirable.
>> As they are the overlapping instances with ad hoc resolution - more
>> generic than allowed by recent Haskell compilers.


Michael Hobbs <[EMAIL PROTECTED]>  writes

> When considering changes to a language, I think one needs to carefully
> measure the difference between convenience and necessity/correctness. I
> think everyone will agree that ad hoc polymorphism (aka overloading) is
> very _convenient_ but I don't think that everyone will agree that it is
> the _correct_ thing to do. I know a few OO purists who will insist that
> overloading is a Bad Thing. Their reasoning: If a function does similar
> things, but with different types, define the function in terms of a
> common base class. If two functions do radically different things, but
> happen to be named the same, you have a naming problem. One of the
> functions should change its name.
> ...
> Perhaps a "better" solution than ad hoc polymorphism would be to provide
> a more convenient namespace syntax. 
> ...


Naming policy would not help.
For example, in the below example, the user of application program has to 
set in one's module  
  let
    det = det_generic  -- choice:  det_Gauss, det_interpolation ...
    ...
    f m n = (det m) + (det n) ...
    ...
Normally, the user has *not* to remember and to think which name to 
apply for one and the same operation. 
Thus, engineers, scientists simply set `det(M)' - do not mention how it
is computed - but presume, that in each situation it is computed in
some appropriate way.  The system has to get automatically to the more 
or less efficient special case in the circumstances.

Here is the practice.
My program suffers from the matrix determinant being called with the 
three different names.
There are known at least three different ways, with essentially 
different cost, to compute the matrix determinant - each usable in the
proper circumstances:

det :: Num a         => [[a]] -> a                         --(N)
       Euclidean a   => [[a]] -> a                         --(E)
       FiniteField a => [[Polynomial a]] -> Polynomial a   --(FFP)
                                            --univariate

Everyone will agree, the name `det' should be the same.
Algorithmically, the preference is:

  if  (FFP) instance fits  then  apply interpolation method
  else 
    if  (E) fits  then 
                     apply Gauss-like method with remainder division
    else
      if  (N) fits  then  apply expansion by row that uses only +,-,*

Further,  Num  is a superclass for Euclidean and for (FFP),
          FiniteField a => Polynomial a  is an instance of Euclidean.


The natural solution is 
  class Lin a where  det :: [[a]] -> a
                     ...
  instance Num a         => Lin a           where  det = det_generic
  instance Euclidean a   => Lin a           where  det = det_GaussLike
  instance FiniteField a => Lin (Polynomial a) where  
                                               det = det_interpolate

Then, the compiler has naturally to understand that here it has the 
instance inclusion FFP -- E -- N  and choose the most special possible
instance in each program. 
And the existing compilers refuse to do this - do i mistake?

Further, i meet the cases now and then when the contexts, like 
(FFP),(E) overlap and no one include in another.
The preferences there have to be set  ad hoc,  for example, by,
declaring the order (?).
This is what i call  ad hoc  polymorphism.  
To my mind, it relates closely to the initial polymorphism requirement
for a polymorphic function - or do you think there is a great 
difference?
On the other hand, could someone explain shortly to me and to other
Haskell users, which fundamental language benefints Haskell may loose 
whith this ad hoc -ing?


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





Reply via email to