We introduce generic types. This requires the following tasks:
* functions that take types as an argument and return a type can be implemented and evaluated (the result of such a function call is called a generic type)
* a function call can be used as the type of an instance (i.e. instances of generic types can be created manually)
* functions that take types as an argument and return a function can be implemented and evaluated (the result of such a function call is called a generic function)
* functions created by a function can be evaluated (i.e. generic functions can be called)
* instance validation (i.e. generic functions can be used as validators for generic types,)
* instance validation works (i.e. I cannot store an instance of a generic type that does not pass validation)
* instances of generic types are displayed correctly in the UX
* functions using generic types as their input or output types can be defined and implemented
This goes hand in hand with changing the data-model to the full data model, in particular:
* change Z10/List from a type to a function taking a type
* change Z8/Function from a type to a function taking a list of types and a type
* change Pair to take two types (note that this is currently on Z22, needs to be updated first)
* update Z4K2 to take a list of Z3s, Z4K3 to the proper Z8, Z8K1 to a list of Z17, Z8K2 a list of Z20, Z8K3 a list of Z16, Z12K1 to Z10(Z11), Z22K1 to Z10(Z21), Z50K1 to Z10(Z3)
* the builtin functions need to change their signatures as well
Once the move to Z8 is done, we can significantly tighten the validation of Z7s. Especially, in a composition or function call,
* every argument with a literal should be compatible with that literal
* every argument with a function call should be compatible with the return type of that function call
* every argument with a function reference should be compatible with that function reference