[Haskell] Per-type function namespaces (was: Data.Set whishes)
ozone at algorithm.com.au
ozone at algorithm.com.au
Fri Feb 27 02:53:50 EST 2004
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
More information about the Haskell
mailing list