Compendium of Examples that ought to work more nicely

In general, each entry should have a section header, a description of the problem, and a possible solution.

Omit type information for local mutable variables

(Courtesy Victor Luchangco)

In the conjugate gradient code, we need to include types in the declarations of the mutable local variables. Other languages with type inference don't include such declarations, saying that the types are inferred from the initialization and the uses. We should still require type information for global variables and fields, where we can't see all the use sites. But for local variables, I think we should be able to do this inference too. Then we could leave off the declarations, making the code prettier. That is, we could write:

Loading...

Proposed solution

Perform type inference for local mutable variables, and make type declarations optional for these variables.

Cannot use typecase on type variables

The typecase construct works only on expressions, and not on type variables. This can be very frustrating when you're writing a factory for a parametric type. For example, the factories for arrays in Fortress currently check whether the array contents are numeric, and if so return a vector or matrix. TypeVariableMatching describes the programming trick for doing this matching co-, contra-, or invariantly.

Proposed solution

Permit typecase to be used on type variables, like so:

Loading...

This match would be covariant by default, with where clause constraints permitting invariant or contravariant matching in the future. Type checking this construct simply involves imposing a new (smaller) upper bound on T when checking each RHS.

Self-typing for Result types

In FortressLibrary there are several instances of types that occur in matched pairs, where the supertype is intended to be user-exposed and doesn't use the self-typing idiom, and where the subtype uses self typing and is the type that actually gets extended; this permits implementations to share method definitions that provide precise return type information. Here is one such example (trimmed quite a bit):

Loading...

It would be useful to have some kind of self typing that would permit us to refer to a ReadableArray[\E,I\] and yet be able to inherit decent implementations of fill(...) without the extra interposed type. Note that this refers to use of self types in result contexts (I hesitate to mis-use the terms covariant or contravariant here, but that is what I mean).

Note that from the client's perspective, this is like having a fresh copy of the method code in each instance, but still knowing that, given a ReadableArray[\E,I\], I'm allowed to call fill(...) and get back another ReadableArray[\E,I\].

Proposed solution

Have a notion of self type that can be used in result contexts.

Self typing for argument contexts

A different kind of self typing also occurs frequently in FortressLibrary. This constrains the arguments to method to match the type of the receiving object. A standard example is AdditiveGroup:

Loading...

This prevents us from mistakenly adding a ZZ32 to an Vector[\RR64\]. Note that it *also* promises that we'll return a ZZ32 when we add two ZZ32s together.

This use of self typing is very different from the previous one. Note in particular that there isn't a common supertype API here (unless we impose one). Note also that most of the methods are abstract: we need to provide a separate implementation for each AdditiveGroup, and those implementations will be very different from one another.

Note also that it might make sense for several types in an extends-chain to all extend AdditiveGroup[\self\]; for example, we might imagine declaring Number extends AdditiveGroup[\Number\] and later ZZ32 extends { Number, AdditiveGroup[\ZZ32\].

It would be nice to have a self typing idiom for this situation as well. Note that I'm carefully distinguishing this use of self typing - where the resulting types are not mutually compatible - from the previous one, where they are.

Proposed Solution

Have a form of self typing that permits multiple extension and allows use of self types in both argument and result contexts.