[Grace-core] [] for types' type parameters (with possible application to classes)

Michael Homer mwh at ecs.vuw.ac.nz
Thu Nov 13 15:31:11 PST 2014


Tim and I had a discussion after last week's conference about how
types should be encoded. There is an issue surrounding type
parameters: the existence of generic parameters mean that types must
conceptually be represented (at least dynamically) as methods, which
isn't ideal. Aliasing and reification are the main issues, and the
fact that types and other patterns end up with a strange behavioural
difference. A type accessed from a type definition and a type accessed
from a type parameter will be conceptually different: one is a method
request of something, and the other is a local variable access, but
they're both just accessing a type by its name.

Instead, we could have (reified) types consistently be objects,
generally bound to names. Providing them with generic parameters would
use an ordinary method call. A plausible method to use is the existing
postcircumfix [] operator from the specification.

In this case we would fully abandon the use of <> for generic type
parameters on types. <> would be reserved for declaring and requesting
methods only. Types would always use []. Static typing would be
exactly the same as it has been, with just the syntax different.

Given a type currently written:
    type List<T> = type { first -> T ... }
there is be an object in existence representing the type. That object
is bound to the name "List". It is, itself, a pattern, matching
List<Unknown> (that is, all lists).

In this design the object would also have a method [], which would
specialise the type according to the provided parameters. It would
return an object representing the newly-instantiated type. The
implementation of [] would be internal, and memoise the results. So:
    def ListOfStrings = List[String]
will create an alias for the instantiated type, while
    def MyList = List
will alias the uninstantiated type - these are always genuine object
references. In both cases, the same object will always be returned.
Importantly, the "MyList" alias can be specialised in exactly the same
way, because it is a real object alias.

All occurrences of parameterised types would use the same syntax:
    var x : List[String] := ...
    method lengths<T <: Measurable>(l : List[T]) -> List[Number] { ... }
    type Listable[T] = type { asList -> List[String] }
But to request the "lengths" method, you would still use <>:
    lengths<String>(x)
In this way types and methods are clearly separated, and types are
always first-class.

This also raises some possibilities of higher-kinded types, because
objects can be passed around and have methods requested of them in the
ordinary way. That might be useful in some cases. It's unclear whether
it should be possible to re-specialise the type:
    def ListOfStringNumbers = ListOfString[Number]
If it is possible to do, the types should probably be &ed together.

It is possible that this same approach could be applied to classes, if
instantiating generic parameters on the class itself is considered
useful. The class would be an object, able to be specialised by
requesting its [] method, or instantiated with its constructor method.
This complicates the encoding, but retains the class as a first-class
object.
-Michael


More information about the Grace-core mailing list