Tealeaves.Examples.SystemF.Syntax

From Tealeaves Require Export
  Theory.DecoratedTraversableMonad
  Theory.Multisorted.DecoratedTraversableMonad
  Backends.Multisorted.LN
  Simplification.Simplification
  Simplification.MBinddt.

Export LN.Notations.

#[local] Generalizable Variables F G A B C ϕ.

The index K

Inductive K2 : Type := ktyp | ktrm.

#[export] Instance Keq : EqDec K2 eq.
Proof.
  change ( x y : K2, {x = y} + {x y}).
  decide equality.
Defined.

#[export] Instance I2 : Index := {| K := K2 |}.

System F syntax and typeclass instances

Parameter base_typ : Type.

Section syntax.

  Context
    {V : Type}.

  Inductive typ : Type :=
  | ty_c : base_typ typ
  | ty_v : V typ
  | ty_ar : typ typ typ
  | ty_univ : typ typ.

  Inductive term : Type :=
  | tm_var : V term
  | tm_abs : typ term term
  | tm_app : term term term
  | tm_tab : term term
  | tm_tap : term typ term.

End syntax.

Clear the implicit arguments to the type constructors. This keeps V implicit for the constructors.
Arguments typ V : clear implicits.
Arguments term V : clear implicits.

Definition SystemF (k : K) (v : Type) : Type :=
  match k with
  | ktyptyp v
  | ktrmterm v
  end.

Notations

Module Notations.

  Declare Scope SystemF_scope.

Notations for type expressions

  Notation "A ⟹ B" := (ty_ar A B) (at level 51, right associativity) : SystemF_scope.
  Notation "∀ τ" := (ty_univ τ) (at level 60) : SystemF_scope.

Notations for term expressions

  Notation "'λ' X ⋅ body" := (tm_abs X body) (at level 45) : SystemF_scope.
  Notation "t1 @ t2" := (tm_app t1 t2) (at level 40) : SystemF_scope.
  Notation "'Λ' body" := (tm_tab body) (at level 45) : SystemF_scope.
  Notation "t1 @@ t2" := (tm_tap t1 t2) (at level 40) : SystemF_scope.

Coercions from variables to leaves

  Coercion Fr : atom >-> LN.
  Coercion Bd : nat >-> LN.

Coercions from leaves to term expressions

  Definition tm_var_ : LN term LN := @tm_var LN.
  Coercion tm_var_ : LN >-> term.

Coercions from leaves to type expressions

  Definition c_base_type: base_typ typ LN := @ty_c LN.
  Definition c_LN_type : LN typ LN := @ty_v LN.
  Coercion c_base_type : base_typ >-> typ.
  Coercion c_LN_type : LN >-> typ.

End Notations.

Open Scope SystemF_scope.
Import Notations.

Example expressions

Module examples.

  Context
    (x y z : atom)
    (c1 c2 c3 : base_typ).

Raw abstract syntax

Abstract syntax trees without notations or coercions

Constants and variables

  Example typ_1 : typ LN := ty_v (Fr x).
  Example typ_2 : typ LN := ty_v (Fr y).
  Example typ_3 : typ LN := ty_v (Fr z).
  Example typ_4 : typ LN := ty_v (Bd 0).
  Example typ_5 : typ LN := ty_v (Bd 1).
  Example typ_6 : typ LN := ty_v (Bd 2).
  Example typ_7 : typ LN := ty_c c1.
  Example typ_8 : typ LN := ty_c c2.

Simple types

  Example typ_9 : typ LN := ty_ar (ty_v (Fr x))
                                     (ty_v (Fr x)).
  Example typ_10 : typ LN := ty_ar (ty_v (Fr x))
                                     (ty_v (Fr y)).
  Example typ_11 : typ LN := ty_ar (ty_v (Fr x))
                                     (ty_v (Bd 1)).
  Example typ_12 : typ LN := ty_ar (ty_v (Bd 1))
                                     (ty_c c1).
  Example typ_13 : typ LN := ty_ar (ty_ar (ty_v (Bd 0))
                                            (ty_v (Fr x)))
                                     (ty_v (Bd 1)).
  Example typ_14 : typ LN := ty_ar (ty_c c2)
                                     (ty_ar (ty_v (Fr x))
                                            (ty_v (Bd 1))).
  Example typ_15 : typ LN := ty_ar (ty_ar (ty_v (Bd 2))
                                            (ty_c c1))
                                     (ty_ar (ty_v (Fr y))
                                            (ty_v (Fr x))).
  Example typ_16 : typ LN := ty_ar (ty_ar (ty_v (Bd 2))
                                            (ty_v (Bd 1)))
                                     (ty_ar (ty_v (Fr y))
                                            (ty_v (Fr x))).

Universal types

  Example typ_17 : typ LN := ty_univ (ty_ar (ty_v (Bd 0))
                                              (ty_v (Bd 0))).
  Example typ_18 : typ LN := ty_univ (ty_ar (ty_ar (ty_v (Bd 2))
                                                     (ty_v (Bd 1)))
                                              (ty_ar (ty_v (Fr y))
                                                     (ty_v (Fr x)))).

Printy printed syntax

  Module pretty.

    #[local] Open Scope SystemF_scope.

    Compute (0 : typ LN).
    Compute (x : typ LN).
    Compute (c1 : typ LN).

Constants and variables
    Example typ_1 : typ LN := x.
    Example typ_2 : typ LN := y.
    Example typ_3 : typ LN := Fr z.
    Example typ_4 : typ LN := 0.
    Example typ_5 : typ LN := Bd 1.
    Example typ_6 : typ LN := 2.
    Example typ_7 : typ LN := c1.
    Example typ_8 : typ LN := c2.

Simple types
    Example typ_9 : typ LN := x x.
    Example typ_10 : typ LN := x y.

    Goal ((x x : typ LN) = Fr x Fr x). reflexivity. Qed.
    Goal ((x 1 : typ LN) = Fr x Bd 1). reflexivity. Qed.

    Example typ_11 : typ LN := x 1.
    Example typ_12 : typ LN := x c1.
    Example typ_13 : typ LN := (x 0) 1.
    Example typ_14 : typ LN := c2 (x 1).

    Goal c2 x 1 = c2 (x 1). reflexivity. Qed.

    Example typ_15 : typ LN := (2 c1) (y x).
    Example typ_16 : typ LN := (2 1) (y x).

Universal types
    Example typ_17 : typ LN := (0 0).
    Goal (0 0) = 0 0. reflexivity. Qed.

    Example typ_18 : typ LN := (2 1) (y x).
    Goal (2 1) (y x) = ((2 1) (y x)). reflexivity. Qed.

    Example typ_19 : typ LN := ( 2 1) (y x).
    Example typ_20 : typ LN := (2 1) y x.

  End pretty.

  Example term_1 : term LN := tm_var (Fr x).
  Example term_2 : term LN := tm_var (Bd 0).
  Example term_3 : term LN := tm_app term_1 term_2.
  Example term_4 : term LN := tm_app term_3 term_3.

Identity function on type c1.
  Example term_5 : term LN := tm_abs (ty_c c1) (tm_var (Bd 0)).
  Example term_6 : term LN := tm_app term_5 term_3.

Polymorphic identity function.
  Example term_7 : term LN := tm_tab (tm_abs (ty_v (Bd 0))(tm_var (Bd 0))).

Instantiate identity at c1
  Example term_8 : term LN := tm_tap term_7 c1.

  #[local] Open Scope SystemF_scope.

  Example term_9 : term LN := (Λ λ 0 0).

End examples.

binddt operations

Section operations.

  Context
    (F : Type Type)
    `{Applicative F}
    {A B : Type}.

  Fixpoint bind_type (f : (k : K), list K2 × A F (SystemF k B)) (t : typ A) : F (typ B) :=
    match t with
    | ty_c t
        pure (ty_c t)
    | ty_v a
        f ktyp (nil, a)
    | ty_ar t1 t2
        pure ty_ar <⋆> bind_type f t1 <⋆> bind_type f t2
    | ty_univ body
        pure ty_univ <⋆> bind_type (f allK (incr [ktyp])) body
    end.

  Fixpoint bind_term (f : (k : K), list K2 × A F (SystemF k B)) (t : term A) : F (term B) :=
    match t with
    | tm_var a
        f ktrm (nil, a)
    | tm_abs ty body
        pure tm_abs
        <⋆> bind_type f ty
        <⋆> bind_term (f allK (incr [ktrm])) body
    | tm_app t1 t2
        pure tm_app <⋆> bind_term f t1 <⋆> bind_term f t2
    | tm_tab body
        pure tm_tab <⋆> bind_term (f allK (incr [ktyp])) body
    | tm_tap t1 ty
        pure tm_tap <⋆> bind_term f t1 <⋆> bind_type f ty
    end.

End operations.

#[export] Instance MReturn_SystemF : MReturn SystemF :=
  fun A kmatch k with
          | ktypty_v
          | ktrmtm_var
          end.

#[export] Instance MBind_type : MBind (list K2) SystemF typ := @bind_type.
#[export] Instance MBind_term : MBind (list K2) SystemF term := @bind_term.
#[export] Instance MBind_SystemF : k, MBind (list K2) SystemF (SystemF k) :=
  ltac:(intros [|]; typeclasses eauto).

Ltac cbn_mbinddt_post_hook ::=
  try match goal with
  | |- context[bind_type ?G ?f ?τ] ⇒
      change (bind_type G f τ) with (mbinddt typ G f τ)
  | |- context[bind_term ?G ?f ?t] ⇒
      change (bind_term G f t) with (mbinddt term G f t)
    end.

(*
Ltac simplify_mbinddt_unfold_ret_hook ::=
  unfold_ops @MReturn_SystemF.
*)


Ltac use_operational_tcs :=
  ltac_trace "use_operational_tcs";
  change (bind_type ?F ?f) with (mbinddt typ F f).

Ltac grammatical_categories_down :=
  ltac_trace "grammatical_categories_down";
  change (SystemF ktyp) with typ;
  change (MBind_SystemF ktyp) with MBind_type.

Ltac grammatical_categories_up :=
  ltac_trace "grammatical_categories_up";
  change typ with (SystemF ktyp);
  change (MBind_type) with (MBind_SystemF ktyp).

Ltac K_down :=
  ltac_trace "K_down";
  change (@K I2) with K2.

Ltac K_up :=
  ltac_trace "K_up";
  change K2 with (@K I2).

Example computations

Section example_computations.

  Open Scope SystemF_scope.

  Context
    (x y z : atom)
    (c1 c2 c3 : base_typ).

Demo of opening operation

  Goal open (T := SystemF) typ ktyp (Fr x) (Bd 0) = Fr x. reflexivity. Qed.
  Goal open typ ktyp (Fr x) (Bd 1) = Bd 0. reflexivity. Qed.
  Goal open typ ktyp (Fr x) (Fr x) = Fr x. reflexivity. Qed.
  Goal open typ ktyp (Fr x) (Fr y) = Fr y. reflexivity. Qed.
  Goal open typ ktyp (Fr y) (Fr x) = Fr x. reflexivity. Qed.
  Goal open typ ktyp (Fr y) (Fr y) = Fr y. reflexivity. Qed.
  Goal open typ ktyp (Fr x) (∀ Bd 0) = (∀ (Bd 0)). reflexivity. Qed.
  Goal open typ ktyp (Fr x) (∀ Bd 1) = (∀ (Fr x)). reflexivity. Qed.
  Goal open typ ktyp (Fr x) (∀ (Bd 1 Bd 0)) = (∀ Fr x Bd 0). reflexivity. Qed.
  Goal open typ ktyp (Fr x) (∀ Bd 1 Bd 2) = (∀ Fr x Bd 1). reflexivity. Qed.

End example_computations.

Proofs of the DTM axioms

Helper lemmas for proving DTM axioms

Section DTM_instance_lemmas.

  Context
    (W : Type)
    (S : Type Type)
    (T : K Type Type)
    `{! MReturn T}
    `{! MBind W T S}
    `{! k, MBind W T (T k)}
    {mn_op : Monoid_op W}
    {mn_unit : Monoid_unit W}.

  Lemma mbinddt_inst_law1_case1 : (A : Type) (t : S A) (w : W),
      (mbinddt S (fun AA) (fun kmret T k extract (W := (W ×))) t = t)
      (mbinddt S (fun AA) (fun k(mret T k extract (W := (W ×))) ⦿ w) t = t).
  Proof.
    introv IH. rewrite <- IH at 2.
    fequal. ext k [w' a]. easy.
  Qed.

  Lemma mbinddt_inst_law1_case12 : (A : Type) (w : W),
      mbinddt S (fun AA) (fun kmret T k extract (W := (W ×))) (A := A) =
        mbinddt S (fun AA) ((fun kmret T k extract (W := (W ×))) allK (incr w)).
  Proof.
    introv. fequal. now ext k [w' a].
  Qed.

  Context
    `{Applicative G}
    `{Applicative F}
    `{! Monoid W}
    {A B C : Type}
    (g : k, W × B G (T k C))
    (f : k, W × A F (T k B)).

  (* for Var case *)
  Lemma mbinddt_inst_law2_case2 : (a : A) (k : K),
    map (F := F) (mbinddt (T k) G g) (f k (Ƶ, a)) =
    map (F := F) (mbinddt (T k) G (g allK (incr Ƶ))) (f k (Ƶ, a)).
  Proof.
    intros.
    repeat fequal.
    ext k' [w b].
    rewrite vec_compose_allK2.
    unfold compose. cbn.
    now simpl_monoid.
  Qed.

End DTM_instance_lemmas.

mbinddt_mret

Lemma mbinddt_mret_typ : (A: Type),
    mbinddt typ (fun AA) (mret SystemF allK extract) = @id (typ A).
Proof.
  intros. ext t. unfold id. induction t.
  - simplify_mbinddt. reflexivity.
  - simplify_mbinddt. reflexivity.
  - simplify_mbinddt.
    fequal.
    apply IHt1.
    apply IHt2.
  - cbn. fequal.
    rewrite vec_compose_assoc.
    K_up.
    rewrite vec_compose_allK.
    rewrite extract_incr.
    assumption.
Qed.

Lemma mbinddt_mret_term : (A : Type),
    mbinddt term (fun AA) (mret SystemF allK (extract (W := (list K2 ×)))) = @id (term A).
Proof.
  intros. ext t. unfold id. induction t.
  - simplify_mbinddt. reflexivity.
  - cbn_mbinddt.
    fequal
    + use_operational_tcs.
      now rewrite mbinddt_mret_typ.
    + rewrite vec_compose_assoc.
      K_up.
      rewrite vec_compose_allK.
      rewrite extract_incr.
      assumption.
  - cbn. fequal.
    + apply IHt1.
    + apply IHt2.
  - cbn. fequal.
    rewrite vec_compose_assoc.
    K_up.
    rewrite vec_compose_allK.
    rewrite extract_incr.
    assumption.
  - cbn. fequal.
    + apply IHt.
    + now rewrite mbinddt_mret_typ.
Qed.

mbinddt_mbinddt

Lemma mbinddt_mbinddt_typ :
   (F : Type Type)
    (G : Type Type)
    `{Applicative F}
    `{Applicative G}
    `(g : k, list K2 × B G (SystemF k C))
    `(f : k, list K2 × A F (SystemF k B)),
    map (F := F) (mbinddt typ G g) mbinddt typ F f =
    mbinddt typ (F G) (g dtm f).
Proof.
  intros. ext t. generalize dependent f. generalize dependent g.
  unfold compose at 1. induction t; intros g f.
  - cbn.
    rewrite (app_pure_natural).
    reflexivity.
  - cbn.
    change (MBind_type ?G ?Map ?Pure ?Mult ?A ?B) with
      (mbinddt typ G (A := A) (B := B)).
    change [] with (Ƶ : list K2).
    change typ with (SystemF ktyp).
    unfold vec_compose.
    Set Keyed Unification.
    rewrite <- (mbinddt_inst_law2_case2 (list K2)
                 SystemF (H := MBind_SystemF) _ _ _ ktyp).
    Unset Keyed Unification.
    reflexivity.
  - cbn.
    rewrite <- IHt1.
    rewrite <- IHt2.
    do 2 rewrite (ap_compose2 G F).
    rewrite <- (ap_map (G := F)).
    rewrite <- (ap_map (G := F)).
    do 2 rewrite map_ap.
    do 2 rewrite map_ap.
    assert (Functor F) by apply app_functor.
    do 3 (compose near (pure (F := (F G)) (ty_ar (V := C)));
          rewrite (fun_map_map (F := F))).
    unfold_ops @Pure_compose.
    rewrite (app_pure_natural).
    rewrite (app_pure_natural).
    reflexivity.
  - cbn.
    setoid_rewrite compose_dtm_incr_alt.
    rewrite <- IHt.
    rewrite (ap_compose2 G F).
    rewrite <- (ap_map (G := F)).
    compose near (pure (F := F G) (ty_univ (V := C))).
    assert (Functor F) by apply app_functor.
    rewrite (fun_map_map (F := F)).
    unfold_ops @Pure_compose.
    rewrite (app_pure_natural).
    rewrite map_ap.
    rewrite (app_pure_natural).
    reflexivity.
Qed.

Lemma mbinddt_mbinddt_term :
   (F : Type Type)
    (G : Type Type)
    `{Applicative F}
    `{Applicative G}
    `(g : k, list K2 × B G (SystemF k C))
    `(f : k, list K2 × A F (SystemF k B)),
    map (F := F) (mbinddt term G g) mbinddt term F f =
    mbinddt term (F G) (g dtm f).
Proof.
  intros. ext t. generalize dependent f. generalize dependent g.
  unfold compose at 1. induction t; intros g f;
    assert (Functor F) by apply app_functor.
  - cbn.
    change (MBind_term ?G ?map ?pure ?mult ?A ?B) with
      (mbinddt term G (A := A) (B := B)).
    fequal. fequal. now ext k [w a].
  - cbn.
    change (bind_type ?F ?f) with (mbinddt typ F f).
    setoid_rewrite compose_dtm_incr_alt.
    rewrite <- IHt.
    rewrite <- (mbinddt_mbinddt_typ F G).
    unfold compose at 2.
    do 2 rewrite (ap_compose2 G F).
    unfold compose.
    do 2 rewrite <- (ap_map (G := F)).
    unfold_ops @Pure_compose.
    rewrite (app_pure_natural).
    do 4 rewrite map_ap.
    compose near ((pure (F := F) (ap G (pure (F := G) (@tm_abs C))))).
    rewrite (fun_map_map (F := F)).
    do 3 rewrite (app_pure_natural).
    reflexivity.
  - cbn.
    rewrite <- IHt1.
    rewrite <- IHt2.
    do 2 rewrite (ap_compose2 G F).
    do 2 rewrite <- (ap_map (G := F)).
    do 4 rewrite map_ap.
    compose near (pure (F := F G) (@tm_app C)).
    rewrite (fun_map_map (F := F)).
    compose near (pure (F := F G) (@tm_app C)).
    rewrite (fun_map_map (F := F)).
    compose near (pure (F := F G) (@tm_app C)).
    rewrite (fun_map_map (F := F)).
    unfold_ops @Pure_compose.
    do 2 rewrite (app_pure_natural).
    reflexivity.
  - cbn.
    setoid_rewrite (compose_dtm_incr_alt).
    rewrite <- IHt.
    rewrite (ap_compose2 G F).
    rewrite <- (ap_map (G := F)).
    rewrite map_ap.
    unfold_ops @Pure_compose.
    do 3 rewrite (app_pure_natural).
    reflexivity.
  - cbn.
    rewrite <- IHt.
    rewrite <- (mbinddt_mbinddt_typ F G).
    unfold compose at 4.
    do 2 rewrite (ap_compose2 G F).
    repeat rewrite <- (ap_map (G := F)).
    change (bind_type ?F ?f) with (mbinddt typ F f).
    do 4 rewrite map_ap.
    compose near (pure (F := F G) (@tm_tap C)).
    rewrite (fun_map_map (F := F)).
    compose near (pure (F := F G) (@tm_tap C)).
    rewrite (fun_map_map (F := F)).
    compose near (pure (F := F G) (@tm_tap C)).
    rewrite (fun_map_map (F := F)).
    unfold_ops @Pure_compose.
    rewrite (app_pure_natural).
    rewrite (app_pure_natural).
    reflexivity.
Qed.

mbinddt_morphism


#[local] Set Keyed Unification.

Lemma mbinddt_morphism_typ :
   (F : Type Type)
    (G : Type Type)
    `{ApplicativeMorphism F G ϕ}
    `(f : k, list K2 × A F (SystemF k B)),
    ϕ (typ B) mbinddt typ F f =
    mbinddt typ G (fun kϕ (SystemF k B) f k).
Proof.
  intros. ext t. generalize dependent f. unfold compose. induction t; intro f.
  - cbn. rewrite (appmor_pure). reflexivity.
  - reflexivity.
  - cbn.
    rewrite <- IHt1. clear IHt1.
    rewrite <- IHt2. clear IHt2.
    rewrite ap_morphism_1.
    rewrite ap_morphism_1.
    rewrite (appmor_pure).
    reflexivity.
  - cbn.
    rewrite <- IHt. clear IHt.
    rewrite ap_morphism_1.
    rewrite (appmor_pure).
    reflexivity.
Qed.

Lemma mbinddt_morphism_term :
   (F : Type Type)
    (G : Type Type)
    `{ApplicativeMorphism F G ϕ}
    `(f : k, list K2 × A F (SystemF k B)),
    ϕ (term B) mbinddt term F f =
    mbinddt term G (fun kϕ (SystemF k B) f k).
Proof.
  intros. ext t. generalize dependent f. unfold compose. induction t; intro f.
  - reflexivity.
  - cbn.
    rewrite <- IHt. clear IHt.
    do 2 rewrite ap_morphism_1.
    rewrite (appmor_pure).
    change (bind_type ?F ?f) with (mbinddt typ F f).
    compose near t on left.
    rewrite (mbinddt_morphism_typ F G).
    reflexivity.
  - cbn.
    rewrite <- IHt1. clear IHt1.
    rewrite <- IHt2. clear IHt2.
    rewrite ap_morphism_1.
    rewrite ap_morphism_1.
    rewrite (appmor_pure).
    reflexivity.
  - cbn.
    rewrite <- IHt. clear IHt.
    rewrite ap_morphism_1.
    rewrite (appmor_pure).
    reflexivity.
  - cbn.
    rewrite <- IHt. clear IHt.
    do 2 rewrite ap_morphism_1.
    rewrite (appmor_pure).
    change (bind_type ?F ?f) with (mbinddt typ F f).
    compose near t0 on left.
    rewrite (mbinddt_morphism_typ F G).
    reflexivity.
Qed.

#[local] Unset Keyed Unification.

mbinddt_comp_mret

Lemma mbinddt_comp_mret_typ :
   (F : Type Type)
    `{Applicative F}
    `(f : k, list K2 × A F (SystemF k B)),
    mbinddt typ F f mret SystemF ktyp = f ktyp pair nil.
Proof.
  reflexivity.
Qed.

Lemma mbinddt_comp_mret_term :
   (F : Type Type)
    `{Applicative F}
    `(f : k, list K2 × A F (SystemF k B)),
    mbinddt term F f mret SystemF ktrm = f ktrm pair nil.
Proof.
  reflexivity.
Qed.

Corollary mbinddt_comp_mret_F :
   k F `{Applicative F}
    `(f : k, (list K2) × A F (SystemF k B)),
    mbinddt (W := list K2) (T := SystemF) (SystemF k) F f mret SystemF k = (fun af k (Ƶ, a)).
Proof.
  intro k. destruct k.
  - apply mbinddt_comp_mret_typ.
  - apply mbinddt_comp_mret_term.
Qed.

DTPreModule instances

#[export] Instance DTP_typ: MultiDecoratedTraversablePreModule
                              (list K2) SystemF typ :=
  {| dtp_mbinddt_mret := @mbinddt_mret_typ;
     dtp_mbinddt_mbinddt := @mbinddt_mbinddt_typ;
     dtp_mbinddt_morphism := @mbinddt_morphism_typ;
  |}.

#[export] Instance DTP_term: MultiDecoratedTraversablePreModule
                               (list K2) SystemF term :=
  {| dtp_mbinddt_mret := @mbinddt_mret_term;
     dtp_mbinddt_mbinddt := @mbinddt_mbinddt_term;
     dtp_mbinddt_morphism := @mbinddt_morphism_term;
  |}.

#[export] Instance: k, MultiDecoratedTraversablePreModule
                           (list K2) SystemF (SystemF k) :=
  fun kmatch k with
        | ktypDTP_typ
        | ktrmDTP_term
        end.

#[export] Instance: MultiDecoratedTraversableMonad (list K2) SystemF :=
  {| dtm_mbinddt_comp_mret := mbinddt_comp_mret_F;
  |}.

System F type system and operational rules

Reserved Notation "Δ ; Γ ⊢ t : τ" (at level 90, t at level 99).

Contexts and well-formedness predicates

Context of type variables

Definition kind_ctx := alist unit.

Context of term variables

Definition type_ctx := alist (typ LN).

Well-formedness for kinding contexts

A kinding context is well-formed when its keys, i.e. type variables, are unique.
Definition ok_kind_ctx : kind_ctx Prop := uniq.

#[export] Hint Unfold ok_kind_ctx : tea_alist.

Well-formedness of type expressions in a kinding context

A type is well-formed in a kinding context Δ when all of its type variables appear in Δ and the type is locally closed.
Definition ok_type : kind_ctx typ LN Prop :=
  fun Δ τscoped typ ktyp τ (domset Δ) LC typ ktyp τ.

Well-formedness for typing contexts

A typing context Γ is well-formed in kinding context Δ when the keys of Γ (i.e. term variables) are unique, and each associated type is itself well-formed in context Δ.
Definition ok_type_ctx : kind_ctx type_ctx Prop :=
  fun Δ Γuniq Γ τ, τ range Γ ok_type Δ τ.

Well-formedness of term expressions in context

A term t is well-formed in contexts Δ and Γ when its type variables are declared in Δ, its term variables are declared in Γ, and it is locally closed with respect to both kinds of variables.
Definition ok_term : kind_ctx type_ctx term LN Prop :=
  fun Δ Γ tscoped term ktyp t (domset Δ)
            scoped term ktrm t (domset Γ)
            LC term ktrm t
            LC term ktyp t.

Typing judgments

Implicit Types (Δ : kind_ctx) (Γ : type_ctx) (τ : typ LN).

Inductive Judgment : kind_ctx type_ctx term LN typ LN Prop :=
| j_var :
     Δ Γ x τ,
      ok_kind_ctx Δ
      ok_type_ctx Δ Γ
      (x, τ) (Γ : list (atom × typ LN))
      (Δ ; Γ tm_var (Fr x) : τ)
| j_abs :
     Δ Γ (L:AtomSet.t) t τ1 τ2,
      ( x, x `notin` L
            Δ ; Γ ++ x ¬ τ1 open term ktrm (tm_var (Fr x)) t : τ2)
      (Δ ; Γ tm_abs τ1 t : ty_ar τ1 τ2)
| j_app :
     Δ Γ t1 t2 τ1 τ2,
      (Δ ; Γ t1 : ty_ar τ1 τ2)
      (Δ ; Γ t2 : τ1)
      (Δ ; Γ tm_app t1 t2 : τ2)
| j_univ :
     Δ Γ L τ t,
      ( x, x `notin` L
            Δ ++ x ¬ tt ; Γ open term ktyp (ty_v (Fr x)) t
                          : open typ ktyp (ty_v (Fr x)) τ)
      (Δ ; Γ tm_tab t : ty_univ τ)
| j_inst :
     Δ Γ t τ1 τ2,
      ok_type Δ τ1
      (Δ ; Γ t : ty_univ τ2)
      (Δ ; Γ tm_tap t τ1 : open typ ktyp τ1 τ2)
where "Δ ; Γ ⊢ t : τ" := (Judgment Δ Γ t τ).

Values and reduction rules

Inductive value : term LN Prop :=
| val_abs : T t, value (tm_abs T t)
| val_tab : t, value (tm_tab t).

Inductive red : term LN term LN Prop :=
| red_app_l : t1 t1' t2,
    red t1 t1'
    red (tm_app t1 t2) (tm_app t1' t2)
| red_app_r : t1 t2 t2',
    value t1
    red t2 t2'
    red (tm_app t1 t2) (tm_app t1 t2')
| red_abs : T t1 t2,
    value t2
    red (tm_app (tm_abs T t1) t2) (open term ktrm t2 t1)
| red_tapl : t t' T,
    red t t'
    red (tm_tap t T) (tm_tap t' T)
| red_tab : T t,
    red (tm_tap (tm_tab t) T) (open term ktyp T t).

Definition preservation := t t' τ,
    (nil ; nil t : τ)
    red t t'
    (nil ; nil t' : τ).

Definition progress := t τ,
    (nil ; nil t : τ)
    value t t', red t t'.