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

Marco Kesseler m.wittebrood@mailbox.kun.nl
Sun, 12 Oct 2003 17:43:06 +0200


>One important thing that I find lacking in Clean 2.0, and which
>I hope will be addressed in a future release, is proper support
>for Abstract Data Types (ADTs) (aka interfaces in Java).

One of the things that I have been wondering about for some years, is 
why the "classes" as found in Clean actually aren't called 
"interfaces", as they lack an "object state".

>It should be possible, in *any* context where a type needs to be
>specified, to specify by some means an Abstract Data Type, so
>that one or more functions is defined on this abstract type,
>but the actual implementation of the type (in terms of how it
>is represented and how the function(s) is/are implemented)
>can be freely varied on an instance-by-instance basis. "Freely"
>in the sense that the postcondition(s) of the function(s)
>should be adhered to, but the choice of representation should
>be entirely open.

For me, the main question would be what to consider an "instance". In 
Clean, the class implementation must be specified for each type that 
is an instance of the class. And so, the implementation will vary on 
a type-by-type basis. For "objects" within that type, no variations 
are possible, if you look at classes alone.

>The best way to do that in Clean 2.0 seems to be to say
>something like
>
>myfunction::a -> Foo | ADT a
>
>But it is not possible to use the "| ADT a" syntax when
>defining the type of a field in a record type definition,
>for example.

It has been a while since I played with that in Clean, so I am not 
entirely certain anymore what you CAN do syntactically in a record 
type definition. But see below.

>I have had to plump for a particular implementation of the 
>ADT when declaring record types, which is an undesirable hack.
>It reduces the freedom to use more efficient implementations
>depending on the context.
>
>Will this be fixed in a future release? Or is there some
>alternative way of doing what I want to do that I've missed?

You might consider defining your own "classes", in the sense that you 
can create records that contain fields AND functions that act on that 
same object (including its fields). Effectively, you have then built 
your own function table. The "only" thing that Clean does not do for 
you, is pass the object implicitly as an argument to its functions, 
so you may will have to define functions for that. For example.

// A class with one field, and two "methods"

:: Integer = {
		value	:: Int,
		inc		:: Integer -> Integer,
		print	:: Integer -> String
	}

// Auxiliary functions (not needed in OO languages)

inc :: Integer -> Integer
inc i = i.inc i

print :: Integer -> String
print i = i.print i

// Two Integer "constructors", with different implementations

myInteger :: Int -> Integer
myInteger i = {Integer |
		value = i,
		inc = \obj -> {obj & value = obj.value + 1},
		print = \obj -> "myInteger: " +++ (toString obj.value)
	}

yourInteger :: Int -> Integer
yourInteger i = {Integer |
		value = i,
		inc = \obj -> {obj & value = obj.value + 2},
		print = \obj -> "yourInteger: " +++ (toString obj.value)
	}

// Let's run

Start = print (inc (inc (myInteger 0)))

This will print "myInteger: 2", but if you replace myInteger by 
yourInteger, the result will be "yourInteger: 4"

It might have been nice to have some syntactic sugar for such 
"objects", especially to avoid the definitions of the inc and print 
functions.

regards,
Marco