[Haskell] Per-type function namespaces (was: Data.Set whishes)

ozone at algorithm.com.au ozone at algorithm.com.au
Fri Feb 27 22:53:49 EST 2004


On 27/02/2004, at 4:48 PM, Brandon Michael Moore wrote:

> On Fri, 27 Feb 2004 ozone at algorithm.com.au wrote:
>
>> On 27/02/2004, at 1:13 PM, oleg at pobox.com wrote:
>>
>> 1) now I have to manually declare a class definition for every single
>> function, and I have to declare it in advance before any module 
>> defines
>> that function (most serious problem; see below),
>>
>> 2) I then have to declare instances of that type class for every
>> function I define,
>>
>> 3) the type signature for phase reveals no clues about how to use that
>> function.
>
> Declaring a type class instance is really no problem.

I agree that declaring a type class instance per function is not a huge 
deal (if it can be automatically done by the compiler).  However, 
declaring the instance first requires declaring the type class itself, 
and that _is_ a problem, because that's exactly what I'm trying to work 
around.  Without 20/20 hindsight, you cannot say with certainty what 
type signatures a "generic" function (like 'phase' or even 'add') can 
support, because it's not a generic function, it's a function which is

When you declare a type class, you are making a trade-off: you are 
saying that the interface for this function is forever set in stone, 
and it cannot be changed by any instances under any circumstances.  In 
return for saying that interface is immutable, you get two major 
benefits: (1) an immutable interface, i.e. so you can guarantee that 
whenever you use ==, you _know_ the type signature is :: Eq a => a -> a 
-> Bool, and no instance can try to subvert that (unless your name is 
Oleg ;), and (2) you get very powerful overloading capabilities.

However, the disadvantage of this tradeoff is that because the type 
signature is now set, you just used up another function name in the 
namespace.  So type classes are the wrong approach to solve this 
problem, because what I'm after is being able to clutter up a namespace 
as much as I like with whatever names I like, but I don't want a 
polymorphic function--I want a function which only operates on one 
specific, primary data type.

>> With the per-type namespace separation I'm advocating, you do not need
>> to know and declare in advance that each function "will be" 
>> overloaded,
>> you simply write a FiniteMap.add function and a Set.add function, and
>> you get a simpler form of namespace separation (or overloading) based
>> on the first parameter that's passed to it.  It is a solution which is
>> more _flexible_ than requiring type class definitions, and it is 
>> better
>> than having hungarian notation for functions.  In fact, I think that,
>> right now, if we replaced the current namespace separation offered by
>> the hierarchical module system, and instead only had this sort of
>> per-type namespace separation, things would still be better!
>
> How much of the structure of the first paramater would you look at? 
> Could
> you an implementation for pairs that depended on the actual types in 
> the
> pair? I think you should try to take advantage of the existing type 
> class
> machinery as much as possible here, even if what you want are not 
> exactly
> (standard) type classes.

The idea is if you write "fm.add", you look at the type of fm as much 
as possible.  If you see that fm is polymorphic, all bets are off, and 
the compiler raises an error and quits with prejudice.  If fm is 
monomorphic, you should be able to infer its type (which includes 
pairs/tuples) and thus know which namespace to select to find the 
correct add function.   So the main requirement for this to work is 
whether it's possible to infer the type of fm; since I'm not a type 
theorist, I have no idea if that is in fact possible at all.

>> I realise my idea isn't very general in that it only allows this
>> namespace lookup/overloading based on the type of a single argument
>> parameter, and I think it would be possible with a bit more thinking 
>> to
>> generalise it to work based on multiple arguments (e.g. via
>> argument-dependent lookup, or whatnot).  But even in its current form,
>> I honestly think it offers far more flexibility and would lead to
>> cleaner APIs than is currently possible.
>
> Read the paper and see if you think something like that might be 
> useful.
> In any case, I think there's a decent chance that something useful for
> this would also be useful for building interfaces to object-oriented
> libraries, and vicea versa. I think there's probably something that 
> covers
> both cases nicely and uniformly.

I've had a read of both the SPJ/Shields paper on OO-style overloading 
in Haskell, and I've also had a skim over another paper called "A 
Second Look at Overloading" which describes another overloading 
calculus called System O.  I don't think either paper directly 
addresses the problem I'm trying to solve, although some elements in 
the paper (e.g. closed classes) may provide a framework which is 
capable of addressing the problem, if something like fm.add can be 
translated to such a framework via major syntactic sugar :).


-- 
% Andre Pang : trust.in.love.to.save


More information about the Haskell mailing list