(* ---------------------------------------------------------------------------- *)

(* Simple types. *)

(* These types do not contain any variables. They have no binding structure. *)

Inductive ty :=
  | TyIota: ty
  | TyArrow: ty -> ty -> ty.(* ---------------------------------------------------------------------------- *)

(* Simple types. *)

(* These types do not contain any variables. They have no binding structure. *)

Inductive ty :=
  | TyIota: ty
  | TyArrow: ty -> ty -> ty.(* ---------------------------------------------------------------------------- *)

(* Simple types. *)

(* These types do not contain any variables. They have no binding structure. *)

Inductive ty :=
  | TyIota: ty
  | TyArrow: ty -> ty -> ty.(* The typing judgement of the simply-typed lambda-calculus. *)

Inductive j : env ty -> term -> ty -> Prop :=
  | JVar:
      forall E x T,
      lookup x E = Some T ->
      j E (TVar x) T
  | JAbs:
      forall E t T1 T2,
      j (insert 0 T1 E) t T2 ->
      j E (TAbs t) (TyArrow T1 T2)
  | JApp:
      forall E t1 t2 T1 T2,
      j E t1 (TyArrow T1 T2) ->
      j E t2 T1 ->
      j E (TApp t1 t2) T2.(* The typing judgement of the simply-typed lambda-calculus. *)

Inductive j : env ty -> term -> ty -> Prop :=
  | JVar:
      forall E x T,
      lookup x E = Some T ->
      j E (TVar x) T
  | JAbs:
      forall E t T1 T2,
      j (insert 0 T1 E) t T2 ->
      j E (TAbs t) (TyArrow T1 T2)
  | JApp:
      forall E t1 t2 T1 T2,
      j E t1 (TyArrow T1 T2) ->
      j E t2 T1 ->
      j E (TApp t1 t2) T2.(* The typing judgement of the simply-typed lambda-calculus. *)

Inductive j : env ty -> term -> ty -> Prop :=
  | JVar:
      forall E x T,
      lookup x E = Some T ->
      j E (TVar x) T
  | JAbs:
      forall E t T1 T2,
      j (insert 0 T1 E) t T2 ->
      j E (TAbs t) (TyArrow T1 T2)
  | JApp:
      forall E t1 t2 T1 T2,
      j E t1 (TyArrow T1 T2) ->
      j E t2 T1 ->
      j E (TApp t1 t2) T2.(* The typing judgement of the simply-typed lambda-calculus. *)

Inductive j : env ty -> term -> ty -> Prop :=
  | JVar:
      forall E x T,
      lookup x E = Some T ->
      j E (TVar x) T
  | JAbs:
      forall E t T1 T2,
      j (insert 0 T1 E) t T2 ->
      j E (TAbs t) (TyArrow T1 T2)
  | JApp:
      forall E t1 t2 T1 T2,
      j E t1 (TyArrow T1 T2) ->
      j E t2 T1 ->
      j E (TApp t1 t2) T2.

(* Specifications: *)
Lemma weakening: forall E t T, j E t T -> forall x U E', insert x U E = E' -> j E' (shift x t) T.
Lemma substitution: forall E x t2 T1 T2, j (insert x T1 E) t2 T2 -> forall t1, j E t1 T1 -> j E (subst t1 x t2) T2.
Lemma type_preservation: forall t1 t2, red t1 t2 -> forall E T, j E t1 T -> j E t2 T.
Lemma j_closed: forall E t T, j E t T -> forall k, length E <= k -> closed k t.
Lemma j_agree: forall E1 t T, j E1 t T -> forall E2 k, agree E1 E2 k -> length E1 <= k -> j E2 t T.
Lemma j_empty: forall E t T, j (@empty _) t T -> j E t T.