In a purely nominative type system, values are members of a type if and only if they are declared to be members of that type. For example:
TYPE amount = integer; VAR a amount, i integer;
i as distinct types; integer values could not be assigned to
a and amount values could not be assigned to
i (how one constructs values of either type is not relevant at this point).
Languages like Pascal, Go, and Oberon are nominatively typed. C/C++ is too, but not as strictly.
However, even in languages like Pascal, Go, and Oberon, function/procedure types are still structural.
Take this Oberon-ish example:
TYPE callback = PROCEDURE (i : INT) : BOOL;
You could then assign any procedure that takes a single integer argument and returns a boolean value to a variable of type
callback, even if there is no nominative declaration that the given procedure is of that type.
Is there a good way around this? My reading of the literature seems to say no. Obviously, one could simply do something like:
PROCEDURE Foo(i : INT) RETURNS BOOL IS callback ... END
But that seems silly since it would be an inherently different mechanism for value construction that those for simple types. It rapidly gets uglier if you admit first-class functions.
The best I could come up with would be something along the lines of “allow Smalltalk-like blocks that are assigned to variables of named type”, but that just raises the question of how to construct and type the blocks: they would still be essentially structurally typed.
So, is there any literature that anyone could point me to? Have there been any languages with 100% nominative typing that admitted procedure/function types?
This thought experiment arose after reading up on Tutorial D, which has strict nominal typing (along with an elegant constructor/selector/constraint mechanism) but does not admit function/procedure types.