(** [type_wf n A] states that a type [A] has only free variables up to < [n].
(in other words, all variables occurring free are strictly bounded by [n]). *)
Inductivetype_wf:nat→type→Prop:=
|type_wf_TVarmn:
m<n→
type_wfn(TVarm)
|type_wf_Intn:type_wfnInt
|type_wf_Booln:type_wfnBool
|type_wf_Unitn:type_wfnUnit
|type_wf_TForallnA:
type_wf(Sn)A→
type_wfn(TForallA)
|type_wf_TExistsnA:
type_wf(Sn)A→
type_wfn(TExistsA)
|type_wf_FunnAB:
type_wfnA→
type_wfnB→
type_wfn(A→B)
|type_wf_ProdnAB:
type_wfnA→
type_wfnB→
type_wfn(A×B)
|type_wf_SumnAB:
type_wfnA→
type_wfnB→
type_wfn(A+B)
|type_wf_munA:
type_wf(Sn)A→
type_wfn(μ:A)
|type_wf_refnA:
type_wfnA→
type_wfn(RefA)
.
#[export]HintConstructorstype_wf:core.
(** NOTE: This type system is somewhat non-standard: it does not satisfy preservation!
The reason is that we don't assign types to lambdas below the [Val] constructor (e.g. [Val (RecV ...)]).
The trouble is that substitution does not descend below the [Val] constructor,
which means that the typing context would need to be completely ignored by the [Val] typing (and that would similarly kill preservation).
Note however that the [Val] constructor is quite convenient when working on program verification in Iris.
Also, in our logical relation, (which does not care about preservation), the [Val] constructor lets us get rid of all closedness requirements on lambdas which we'd otherwise need:
in the logical relation, we can first substitute in all the values via parallel substitution, and only after that
the [Rec f x e] reduces to a [Val (RecV f x e)], which after that is automatically closed.
For using the type system, this is not a major restriction: Instead of using [Val $ RecV f x e] we can always just use [Rec f x e] (which will reduce in one step to [Val $ RecV f x e].
*)
ReservedNotation"'TY' Δ ; Γ ⊢ e : A"(atlevel74,e,Aatnextlevel).