-
Notifications
You must be signed in to change notification settings - Fork 9
Description
Hello again,
What is the official policy for desugaring applications of type constructors?
In my translation of Eunoia specs to LambdaPi, I have adopted the useful policy of desugaring 'object-level' applications to the _ operator. I consider applications of programs and builtins to be 'meta-level' applications, and so these stay n-ary.
For example: when translating the program $is_app, the term ($get_arg_list_rec (f x) acc) desugars to ($get_arg_list_rec (_ f x) acc).
This 'mixed' elaboration policy is nice for me for reasons that I won't explain here (although I'm happy to provide more details upon request).
For example, consider elaborating the term (@pair U T)).
First, note the _ constant must have the following (parameterized) type: (-> (-> X Y) X Y) where X and Y are implicit parameters of type Type.
A naive desugaring may give (_ (_ @Pair U) T).
But this is ill-typed because @Pair has type (-> Type (-> Type Type)) (recognizing that -> is right-associative) and U and T both have type Type. So there is no way to unify (-> X Y) with (-> Type (-> Type Type)), because this would require Type : Type, which is known to be inconsistent in 'sufficiently powerful' type systems.
So I come to the conclusion that applications of type constructors (e.g., ->, @Pair, BitVec) must be desugared similarly to 'meta-level' applications. This is difficult (especially in the absence of declare-type), because such constants have the same formal status as 'term-level' constants.
So one needs to detect on-the-fly which constants are type constructors in order to desugar everything correctly. This essentially requires me to implement a type inference algorithm, which is something I was hoping to avoid.
Thanks in advance!