Vague Arguments

Remind the definition of List.
After the definition List.null is a List(String).
List.null is also a List(Trivial).
How can List.null be both List(String) and List(Trivial)?
Because List.null has been vague about its argument.
The type of List.null is actually (vague E: Type) -> List(E).
We can also explicitly apply List.null to a vague argument.
A vague argument is like an implicit argument, but it is resolved during type checking, by the information of the return type.
For example, we can use vague arguments to define a function -- my_list_null, who works just like the data constructor List.null.
Suppose I am the type checker, I am checking my_list_null: List(String).
  1. I infer my_list_null to be (vague E: Type) -> List(E);
  2. I compare the given return type List(String) with List(E);
  3. Now I know E = String;
  4. I insert the vague argument for my_list_null, to get my_list_null(vague String).
We can also define my_list_cons to be like List.cons.