[clean-list] ADTs for fields in record types, please!

Fergus Henderson fjh@cs.mu.OZ.AU
Tue, 14 Oct 2003 01:33:58 +1000


On 13-Oct-2003, Marco Kesseler <m.wittebrood@mailbox.kun.nl> wrote:
> :: Integer = E.i: {
> 		value	:: i,
> 		inc		:: i -> i,
> 		print	:: i -> String
> 	}

If Clean doesn't support existential types with type class constraints,
I suppose you could still combine the two using existential types like
the one above, if you don't mind a bit of additional boilerplate code.
That is, if you have a type class with say two methods,

	class Integer i {
			inc		:: i -> i,
			print   	:: i -> String
		}

then you can define a corresponding (unconstrained) existential type
with a field for the value and an explicit higher-order function field
for each method:

	:: AnyInteger = E.i: {
			value		:: i,
			inc_meth	:: i -> i,
			print_meth	:: i -> String
		}

You can then provide a conversion function to convert from
any instance of the type class to the existential type:

	mkAnyInteger :: i -> AnyInteger | Integer i
	mkAnyInteger i = { value = i & inc_meth = inc & print_meth = print }

You can also make the existential type an instance of the type class,
so that you never need to do any explicit conversions in the other direction:

	instance Integer AnyInteger where {
			inc any=:{ value, inc_meth } =
				{ any & value = inc_meth value }
			print any=:{ value, print_meth } =
				print_meth value
		}

(I hope I got all the syntax roughly right; this is just off the top
of my head, and I don't have a Clean implementation around to test it.)

> I do find the "constructors" more clear in this situation, but the 
> "problem" I have with this, is that the "methods" have to be very 
> specific in their public signature about what parts of the object 
> they refer to. In the end, this affects maintainability of the code, 
> as you have to change the method signatures as soon as they start 
> taking different object fields as arguments, which should be 
> irrelevant for the "external" interface.  This problem also exists in 
> solutions that employ type class constraints: the contraints provide 
> an interface on an _element_ of the object, not on the object 
> _itself_ (or is there a way?).

I didn't really understand what you were getting at there.
Perhaps an example might help to clarify your point.

-- 
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.