[Haskell] Per-type function namespaces (was: Data.Set whishes)
Abraham Egnor
aegnor at antioch-college.edu
Thu Feb 26 13:28:16 EST 2004
I think that this is a problem that can be solved with a simple convention
change, rather than a language extension - instead of appending type
names, I think it would be much better if modules simply used the short,
convenient, common names and expected the user to import them qualified
where overlap is a problem - in short, do exactly what DData does. It's
slightly more verbose than OO-style: "Map.add map key value" instead of
"map.add(key, value);" but I don't think that "what OO does" is a good
language design target.
Another random thought: what you describe sounds awfully similar to
typeclasses, just with a single function in each typeclass.
Abe
ozone at algorithm.com.au writes:
>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
>Haskell at haskell.org
>http://www.haskell.org/mailman/listinfo/haskell
>
More information about the Haskell
mailing list