- Haskell would need to be a lot more specific about exactly where
context reduction takes place.  Consider
f xs x = xs == [x]
Do we infer the type (Eq a) => [a] -> a -> Bool?  Thereby committing to
a particular choice of instance?  Or do we (as GHC does) infer the type
(Eq [a]) => [a] -> a -> Bool, so that if f is applied at (say) type
Char, then an instance Eq [Char] instance would apply.  GHC is careful
to do the latter.

is there actually anything unusual about this example? you're saying that
there are at least two instances for Eq:

   instance Eq a => Eq [a]
   instance Eq [Char]

and best-fit overlap resolution demands that we never apply the first if
the second fits, too. we just can't apply any rules unless we have established
that there are no more specific rules.

GHC enables overlap resolution on a pre-module basis, Hugs on a per-session
basis, so this means that we can never apply any rules unless they have ground
heads (no variables), or we've seen the whole program. which is somewhat of
an obstacle, suggesting that we would want to be more specific about enabling
overlap resolution, and use any trick we know to figure out when we no longer
have to wait for further, more specific instances (or be content to delay most of instance inference to the compilation of Main).

in "functional logic overloading", POPL 2002, Neubauer et al suggested to
enable overlap resolution on a per-class basis, which seems sensible. even
enabling overlap on a per-instance basis might be worth looking into (that is, we would annotate those non-ground instance declarations which we want to be allowed to be overridden by more specific declarations elsewhere). with such finer control, all unannotated instances/classes might become fair game for earlier rule applications.

we can further limit the scope of overlaps by using the module system
to close a set of class instances (this is useful independent of overlaps,
as it allows us to infer when there will be no instance for a given constraint): a set of instances for a class is closed if the class is neither exported nor imported, and if, for any instances with instance contexts, the context constraints are closed as well. [if the class isn't available outside this module, there can't be any direct instances outside, and if the instance context constraints are closed as well, there can't be any indirect instances generated from outside (*)].
of course, simply annotating a class or class export as "closed", and
letting the compiler ensure that there are no further direct instances, would be somewhat simpler. I'm not sure what to do about further
indirect instances in this case?

cheers,
claus

(*) what do I mean by indirect instances:
   module A () where { class Closed a; instance X a => Closed a}
   module B where { import A; instance X t }
   even if Closed is not exported, creating instances for X indirectly
   creates instances for Closed.

_______________________________________________
Haskell-prime mailing list
Haskell-prime@haskell.org
http://haskell.org/mailman/listinfo/haskell-prime

Reply via email to