I've had an idea stewing in my head to do with per-type function namespaces, that the current module namespace discussion reminded me about. The problem is that there is a limited namespace for functions, so that if you define a new data type, it is unwise to call functions which work on that data type a very generic name such as 'add'. An example of this is Data.FiniteMap and Data.Set: both data types define a function to add things to their respective data types.

addToFM :: Ord key => FiniteMap key elt -> key -> elt -> FiniteMap key elt
addToSet :: Ord a => Set a -> a -> Set a


So at the moment, many Haskellers will append the type name to the function to indicate that it only works on that particular data type. In this respect, Haskell is at a disadvantage vs most object-oriented languages, because in them, you can write "x.add", and the type system will perform "object-oriented polymorphism" for you and call the correct add method, no matter if x is a FiniteMap or a Set. Writing "addToFM fm ..." or "addToSet set ..." is surely a lot more inconvenient than writing "fm.add" or "set.add", no?

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 the Set type, that will only get called if the 'x' in "x.add" is of type :: Set. So, like OO languages which inherently give separate namespaces to their different objects, here we give separate namespaces to different (monomorphic) types. In this case, if one simply writes "add" instead of "x.add", the compiler throws an error, because there is no 'add' function defined in the default namespace; add is only defined when a programmer writes "x.add" where x :: FiniteMap or x :: Set[1].

There are a number of means by which the x in x.add can be communicated to the actual function: it's similar to the hidden 'self' or 'this' variable that's present when you invoke a method on an object in OO. Perhaps x is passed to the function as its first parameter, or maybe it could be its last parameter, or even an arbitrary parameter (where the parameter it's passed as could be defined in the type signature of the function). Perhaps 'self' or 'this' could be an implicit parameter. Any one of them will work just fine, I think.

However, this scheme is only for functions which have such a 'primary' data type to be associated with, such as FiniteMap or Set. For functions which are truly polymorphic (such as ==), you still leave them in the default namespace. Perhaps it's sensible to even make it a requirement that functions in the default namespace must be polymorphic: if they are monomorphic, they are associated with operating on a specific data type, so they should belong in a type-specific namespace. You then still guarantee that such commonly-used polymorphic functions cannot be 'hijacked' to have stupid type signatures; i.e. == is always guaranteed to be :: Eq a -> a -> Bool.

Anyhow, feedback is more than welcome; I would certainly welcome this addition if it's feasible. It feels inferior to be typing in 'addToFM foo' all the time when our OO brethren type the simpler and more succinct 'foo.add', especially given that Haskell's type system is far more powerful!

1. I haven't thought hard enough about whether it would be possible to have the same function name in both the 'default' namespace as well as in per-type namespaces, but my gut feeling says it should be OK.


-- % Andre Pang : trust.in.love.to.save _______________________________________________ Haskell mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell

Reply via email to