Library Mtac2.intf.Sorts
Set Universe Polymorphism.
Unset Universe Minimization ToSet.
Unset Universe Minimization ToSet.
Types that can hold either a Prop or a Type
Set Universe Polymorphism.
Unset Universe Minimization ToSet.
Module S.
Inductive Sort : Type := SProp | SType.
Unset Universe Minimization ToSet.
Module S.
Inductive Sort : Type := SProp | SType.
Creates a fresh type according to s
Definition stype_of (s : Sort) : Type :=
match s with SType => Type | SProp => Prop end.
Arguments stype_of !_ : simpl nomatch.
match s with SType => Type | SProp => Prop end.
Arguments stype_of !_ : simpl nomatch.
When working with a sort s, we cannot simply say "we have an
element of stype_of s". For that, we make selem_of T, where
T is a stype_of s.
Definition selem_of@{i j+} {s : Sort} : stype_of@{i j} s -> Type@{j} :=
match s return stype_of s -> Type@{j} with
| SType => fun x => x
| SProp => fun x => x
end.
Arguments selem_of {!_} _ : simpl nomatch.
Fail Local Example CannotMakeAnElementOfaSort s (P : stype_of s) (x : P) := x.
Local Example WeCanWithElemOf s (P : stype_of s) (x : selem_of P) := x.
Definition selem_lift {s : Sort} : @selem_of SType (stype_of s) -> Type :=
match s as s' return @selem_of SType (stype_of s') -> Type with
| SType => fun x => x
| SProp => fun y => y
end.
Definition ForAll
{sort : Sort} {A : Type} :
(A -> stype_of sort) -> stype_of sort :=
match
sort as sort'
return ((A -> stype_of sort') -> stype_of sort')
with
| SProp => fun F => forall a : A, F a
| SType => fun F => forall a : A, F a
end.
Definition Impl {sort : Sort} A (B : stype_of sort) : stype_of sort :=
ForAll (sort := sort) (fun _ : A => B).
Definition Fun {sort} {A : Type} :
forall {F : A -> stype_of sort}, (forall a, selem_of (F a)) -> selem_of (ForAll F) :=
match sort as sort' return
forall {F : A -> stype_of sort'}, (forall a, selem_of (F a)) -> selem_of (ForAll F)
with
| SProp => fun _ f => f
| SType => fun _ f => f
end.
Definition App {sort} {A : Type} : forall {F : A -> _}, selem_of (ForAll (sort := sort) F) -> forall a, selem_of (F a) :=
match sort as sort' return forall F, selem_of (ForAll (sort := sort') F) -> forall a, selem_of (F a) with
| SProp => fun F f a => f a
| SType => fun F f a => f a
end.
Definition Impl_lift {sort} {A : Type} : forall {B : stype_of sort}, (A -> selem_of B) -> selem_of (Impl A B) :=
match sort with
| SProp => fun B f => f
| SType => fun B f => f
end.
Definition lift_Impl {sort} {A : Type} : forall {B : stype_of sort}, selem_of (Impl A B) -> (A -> selem_of B) :=
match sort with
| SProp => fun B f => f
| SType => fun B f => f
end.
End S.
Import S.
Delimit Scope Sort_scope with sort.
Notation "'[sort' '∀' x .. y , T ]" := (ForAll (fun x => .. (fun y => T) ..)) (x binder, y binder) : Sort_scope.
Notation "'[sort' 'λ' x .. y , T ]" := (Fun (fun x => .. (fun y => T) ..)) (x binder, y binder, T at next level) : Sort_scope.
Coercion stype_of : Sort >-> Sortclass.
Coercion selem_of : stype_of >-> Sortclass.
match s return stype_of s -> Type@{j} with
| SType => fun x => x
| SProp => fun x => x
end.
Arguments selem_of {!_} _ : simpl nomatch.
Fail Local Example CannotMakeAnElementOfaSort s (P : stype_of s) (x : P) := x.
Local Example WeCanWithElemOf s (P : stype_of s) (x : selem_of P) := x.
Definition selem_lift {s : Sort} : @selem_of SType (stype_of s) -> Type :=
match s as s' return @selem_of SType (stype_of s') -> Type with
| SType => fun x => x
| SProp => fun y => y
end.
Definition ForAll
{sort : Sort} {A : Type} :
(A -> stype_of sort) -> stype_of sort :=
match
sort as sort'
return ((A -> stype_of sort') -> stype_of sort')
with
| SProp => fun F => forall a : A, F a
| SType => fun F => forall a : A, F a
end.
Definition Impl {sort : Sort} A (B : stype_of sort) : stype_of sort :=
ForAll (sort := sort) (fun _ : A => B).
Definition Fun {sort} {A : Type} :
forall {F : A -> stype_of sort}, (forall a, selem_of (F a)) -> selem_of (ForAll F) :=
match sort as sort' return
forall {F : A -> stype_of sort'}, (forall a, selem_of (F a)) -> selem_of (ForAll F)
with
| SProp => fun _ f => f
| SType => fun _ f => f
end.
Definition App {sort} {A : Type} : forall {F : A -> _}, selem_of (ForAll (sort := sort) F) -> forall a, selem_of (F a) :=
match sort as sort' return forall F, selem_of (ForAll (sort := sort') F) -> forall a, selem_of (F a) with
| SProp => fun F f a => f a
| SType => fun F f a => f a
end.
Definition Impl_lift {sort} {A : Type} : forall {B : stype_of sort}, (A -> selem_of B) -> selem_of (Impl A B) :=
match sort with
| SProp => fun B f => f
| SType => fun B f => f
end.
Definition lift_Impl {sort} {A : Type} : forall {B : stype_of sort}, selem_of (Impl A B) -> (A -> selem_of B) :=
match sort with
| SProp => fun B f => f
| SType => fun B f => f
end.
End S.
Import S.
Delimit Scope Sort_scope with sort.
Notation "'[sort' '∀' x .. y , T ]" := (ForAll (fun x => .. (fun y => T) ..)) (x binder, y binder) : Sort_scope.
Notation "'[sort' 'λ' x .. y , T ]" := (Fun (fun x => .. (fun y => T) ..)) (x binder, y binder, T at next level) : Sort_scope.
Coercion stype_of : Sort >-> Sortclass.
Coercion selem_of : stype_of >-> Sortclass.