11. First order polymorphism

All Felix nominal types support first order polymorphism by way of type schema:
type x[U,V] ..
fun f[U,V] ..
proc g[U,V] ..
class k[U,V] ..
struct s[U,V] ..
union u[U,V] ..
cstruct c[U,V] ..
cclass k[U,B] ..
All such definitions are intrinsically polymorphic: the lack of an explicit schema designator:
  fun f(x:int)=>x;
is simply shorthand for a unit schema:
  fun f[](x:int)=>x;

In addition, modules may also have type schema, however this is just sugar. The semantics are to prepend the schema to the schema of every definition in the module:

  module X[T] {
    fun f(x:int)=>x;
    fun g[U](x:int)=>x;
  }
is equivalent to:
  module X {
    fun f[T](x:int)=>x;
    fun g[T,U](x:int)=>x;
  }

In addition, typdefs may have schema:

  typedef pair[T] = T * T;
Such a parameterised type alias is a special kind of type function or type functor:
  typedef fun pair(T:TYPE):TYPE => T * T;

Type schema parameters also individual constraints:

  fun f[I:fast_sints] ..
says that the type variable I must be instantiated with a member of the typeset of fast_sints. Discrete typesets can be named by a typedef:
  typedef fast_sints = typesetof (tiny, short, int, long, vlong);
The union and intersection of such sets may be calculated with the setwise union and intersection operators:
typedef A = B || C && D;
with the usual precedence.