On Fri, 27 Feb 2004, Simon Peyton-Jones wrote:
The idea that I've been throwing around is to be able to define a separate namespace for each type; a function can either belong in a "global" (default) namespace, or belong in a particular type's namespace. So, in the above example, instead of writing "addToFM fm ...", we could instead associate an 'add' function with the FiniteMap type, so we could write "fm.add ..." instead. Provided that fm's type
is monomorphic, it should be possible to call the 'correct' add function; if we defined another 'add' function that's associated with
Remember, too, that in OO languages the type of 'fm' is usually declared, in advance, by the programmer. In Haskell it isn't. That makes it much harder to figure out which 'add' function is going to be used.
Which 'add' function is chosen depends on type type of 'fm'. But the add function that is chosen in turn influences the type of the other arguments. For example, in the call (fm.add foo), the type of 'foo' is influenced by the choice of 'add'. But the type of 'foo' might (by the magic of type inference) affect the type of 'fm'....
In Haskell today, you can at least tell what value is bound to each identifier in the program, *without* first doing type checking. And the binding story, all by itself, is somewhat complicated. The typing story is also (very) complicated. Winding the two into a single indissoluble whole would make it far more complicated still.
I thought this wasn't the case if there are type classes invovled. What value is "+" bound to in 1 + 1? All I can think is to say that the appropriate value of + is selected based on the types, or to say that the value here is the class member (subsuming several instances). Either way I don't see a method for overloading individual function names having a greatly different story either way. Actually, picking a version of a function (from the versions in scope) based on which type actually works might be useful. It seems to extend the handling of overlapping names in a useful direction again, resolving ambiguity by assuming you meant to write a typeable program. We would probably want some special syntax with the imports to request/flag this behaviour, like "import A; import B; import C; resolve foo". One heuristic would be typechecking with no information on the name(s) and checking that there is a unique way to resolve the ambiguity at each point.
My nose tells me that this way lies madness.
I think the general principle of using types to capture and infer intent is still sound. It would be nice to have ad-hoc overloading also in cases where we don't see a common intent between several functions to capture with a typeclass (intents that we can't capture are arguments for improving the class system). A lot of haskell already looks like madness already anyway :) We just need to find things that look like good madness ;)
But I've been wrong before.
Simon
Brandon