Skip to content

Instantly share code, notes, and snippets.

View EduardoRFS's full-sized avatar
♥️
Laughing at the abysm

Eduardo Rafael EduardoRFS

♥️
Laughing at the abysm
View GitHub Profile
Definition id {A : Prop} (x : A) : A := x.
Definition J1 {A} {x y : A} (p : x = y)
(C : forall y : A, x = y -> Prop) (H : C x eq_refl) : C y p :=
match p as q in (_ = z) return C z q with | eq_refl => H end.
Definition J {A} {x y : A} (p : x = y) :
exist (fun y => x = y) x eq_refl = exist (fun y => x = y) y p.
apply (J1 p); reflexivity.
Defined.
Definition coe {A} {x y : A} (p : x = y) (C : A -> Prop) (H : C x) : C y :=
J1 p (fun z _ => C z) H.

Self Types for better languages

This post intends to promote self types as a safer, simpler, and faster alternative to inductive types and dependent pattern matching at the core of programming languages.

In summary, it should go through the problems that self types try to solve, the problems that they introduce, and then a concrete solution proposed at the end, with a syntax-directed, bidirectional type system with decidable checking.

SYNTAX at the Syntax section.

The problem

Graded MLTT

The system below is a candidate for a novel approach to strong normalization, it is effectively a graded version of MLTT with Type : Type, such that every variable can be used G times, this is also true for usage while constructing types.

The arguments for termination are:

  • every beta in the non-erasable fragment consumes a lambda
  • constructing types is in the non-erasable fragment
  • an infinite type would require infinite lambdas
  • no infinite type, implies in termination of the erasable fragment

Alternatives to Termination

This is a notes file which will hopefully evolve towards being a proper blog post. The formalization of some of the concepts below are very much WIP.

Why, Termination

Usually for a system to be considered logically consistent, it should avoid paradoxes, in terms of programming languages and theorem provers, those often translate to infinite loops.

I will be talking about type systems, you can figure out how to translate those to languages.

Definition notb (b : bool) : bool :=
if b then false else true.
Definition true_neq_false (b : bool) : b = notb b -> False :=
match b as b return b = notb b -> False with
| true => fun p =>
match p in _ = b return
if b then True else False
with
| eq_refl => I
end
Definition id {A : Prop} (x : A) : A := x.
Definition J1 {A} {x y : A} (p : x = y)
(C : forall y : A, x = y -> Prop) (H : C x eq_refl) : C y p :=
match p as q in (_ = z) return C z q with | eq_refl => H end.
Definition J {A} {x y : A} (p : x = y) :
exist (fun y => x = y) x eq_refl = exist (fun y => x = y) y p.
apply (J1 p); reflexivity.
Defined.
Definition coe {A} {x y : A} (p : x = y) (C : A -> Prop) (H : C x) : C y :=
J1 p (fun z _ => C z) H.
Inductive t_eq {A} (x : A) : A -> Type :=
| t_refl : t_eq x x.
Definition coe {A} {x y : A} (C : A -> Type) (p : t_eq x y) (H : C x) : C y :=
match p in (t_eq _ z) return C z with | t_refl _ => H end.
Definition sym {A} {x y : A} (p : t_eq x y) : t_eq y x :=
coe (fun z => t_eq z x) p (t_refl x).
Definition ap {A B x y} (f : A -> B) (H : t_eq x y) : t_eq (f x) (f y) :=
coe (fun z => t_eq (f x) (f z)) H (t_refl (f x)).
Definition coe_inj {A} {x y : A} (C : A -> Type)
(p : t_eq x y) {H1 H2} (H : t_eq (coe C p H1) (coe C p H2)) : t_eq H1 H2.
Definition sig_fst {A B} {p q : {x : A | B x}} (H : p = q)
: proj1_sig p = proj1_sig q :=
eq_rect _ (fun z => proj1_sig p = proj1_sig z) eq_refl _ H.
Definition sig_snd {A B} {p q : {x : A | B x}} (H : p = q)
: eq_rect _ B (proj2_sig p) _ (sig_fst H) = proj2_sig q :=
match H with
| eq_refl => eq_refl
end.
Definition sig_fst {A B} {p q : {x : A | B x}} (H : p = q)
: proj1_sig p = proj1_sig q :=
eq_rect _ (fun z => proj1_sig p = proj1_sig z) eq_refl _ H.
Definition sig_snd {A B} {p q : {x : A | B x}} (H : p = q)
: eq_rect _ B (proj2_sig p) _ (sig_fst H) = proj2_sig q :=
match H with
| eq_refl => eq_refl
end.
Definition sig_fst {A B} {p q : {x : A | B x}} (H : p = q)
: proj1_sig p = proj1_sig q :=
eq_rect _ (fun z => proj1_sig p = proj1_sig z) eq_refl _ H.
Definition sig_snd {A B} {p q : {x : A | B x}} (H : p = q)
: eq_rect _ B (proj2_sig p) _ (sig_fst H) = proj2_sig q :=
match H with
| eq_refl => eq_refl
end.