To re-address Phil's example for Dave Barton and others confused by
overloading: 

  module One (Problematic)

  class Problematic a where
    difficult :: a -> a
  ----------------------------------------------------
  module Two (trouble)

  imports One (Problematic)

  instance Problematic Int where
    difficult n = n+1

  trouble n = difficult (difficult n)
  ----------------------------------------------------
  module Three (confused)

  imports One (Problematic)
  imports Two (trouble)

  instance Problematic Int where
    difficult n = 2*n

  confused :: Int -> Int
  confused =  trouble

The issue is at what point is the overloading of trouble, which would
be typed as 
trouble :: Problematic a => a -> a
is resolved to a concrete type.  There are two different instances supplied
to resolve Problematic(Int): one in module Two and another in module
Three.  If the signature 
  trouble :: Int -> Int
is placed in module Two then the assumption is that the instance in
module Two is used.  However, if the overloading is resolved in Three,
the other definition is used.  What is important is the definition of
Problematic(Int) in force when the type checker encounters this
context during type checking.  The added type signature forces this to
happen in Two; without the signature this happens in Three.

Currently, the C-T rule ensures that only one instance for a given
type - class pair exists and that this instance is visible wherever
both the class and type are in scope.  

The heart of the issue is a fairly deep question of how the class
system is intended to be used.  Currently, it is completely rigid:
there is no way have more than one way of applying a class to a
particular data type.  As a consequence, a user cannot redefine any
instance found in the Prelude.  For example, if a user wants to print
lists in a different way (say perhaps with a length limit) this simply
cannot be done within the confines of the built in Text class.  Also,
there is no way to create Prelude instances for Prelude objects that are not
there since this would require the instance to be part of the Prelude.
I caught Mark Jones writing:

instance (Num a, Num b) => Num (a,b) where
  (a,b) + (c,d) = (a+c,b+d)

Of course this works in Gofer!!

This same problem dictates that an instance cannot be on the opposite
side of an abstraction barrier from the associated class and data
type.  This certainly gets a bit painful.

Allowing multiple instances (as in Phil's example) presents no
implementation problems; the issue is entirely one of choosing either
the current semantic simplicity and rigidity or a more flexible system
with more complex semantics.  Personally, I would choose the
latter!

    John Peterson
    [EMAIL PROTECTED]




Reply via email to