Theory System_F

theory System_F
  imports Main
begin

datatype dty =
    TyVar nat
  | TyArr dty dty
  | TyAll dty

datatype dtm =
    TmVar nat
  | TmApp dtm dtm
  | TmLam dty dtm
  | TmTAbs dtm
  | TmTApp dtm dty

fun ty_shift :: "nat  dty  dty" where
  "ty_shift k (TyVar n) =
    (if n < k then TyVar n else TyVar (Suc n))"
| "ty_shift k (TyArr A B) = TyArr (ty_shift k A) (ty_shift k B)"
| "ty_shift k (TyAll A) = TyAll (ty_shift (Suc k) A)"

fun ty_subst :: "nat  dty  dty  dty" where
  "ty_subst k S (TyVar n) =
    (if n < k then TyVar n else
      if n = k then S else TyVar (n - 1))"
| "ty_subst k S (TyArr A B) =
    TyArr (ty_subst k S A) (ty_subst k S B)"
| "ty_subst k S (TyAll A) =
    TyAll (ty_subst (Suc k) (ty_shift 0 S) A)"

definition ty_subst0 :: "dty  dty  dty"
where
  "ty_subst0 S A = ty_subst 0 S A"

fun tm_shift :: "nat  dtm  dtm" where
  "tm_shift k (TmVar n) =
    (if n < k then TmVar n else TmVar (Suc n))"
| "tm_shift k (TmApp M N) = TmApp (tm_shift k M) (tm_shift k N)"
| "tm_shift k (TmLam A M) = TmLam A (tm_shift (Suc k) M)"
| "tm_shift k (TmTAbs M) = TmTAbs (tm_shift k M)"
| "tm_shift k (TmTApp M A) = TmTApp (tm_shift k M) A"

fun tm_ty_shift :: "nat  dtm  dtm" where
  "tm_ty_shift k (TmVar n) = TmVar n"
| "tm_ty_shift k (TmApp M P) =
    TmApp (tm_ty_shift k M) (tm_ty_shift k P)"
| "tm_ty_shift k (TmLam A M) =
    TmLam (ty_shift k A) (tm_ty_shift k M)"
| "tm_ty_shift k (TmTAbs M) =
    TmTAbs (tm_ty_shift (Suc k) M)"
| "tm_ty_shift k (TmTApp M A) =
    TmTApp (tm_ty_shift k M) (ty_shift k A)"

fun tm_subst :: "nat  dtm  dtm  dtm" where
  "tm_subst k N (TmVar n) =
    (if n < k then TmVar n else
      if n = k then N else TmVar (n - 1))"
| "tm_subst k N (TmApp M P) =
    TmApp (tm_subst k N M) (tm_subst k N P)"
| "tm_subst k N (TmLam A M) =
    TmLam A (tm_subst (Suc k) (tm_shift 0 N) M)"
| "tm_subst k N (TmTAbs M) =
    TmTAbs (tm_subst k (tm_ty_shift 0 N) M)"
| "tm_subst k N (TmTApp M A) =
    TmTApp (tm_subst k N M) A"

definition tm_subst0 :: "dtm  dtm  dtm"
where
  "tm_subst0 N M = tm_subst 0 N M"

fun tm_ty_subst :: "nat  dty  dtm  dtm" where
  "tm_ty_subst k S (TmVar n) = TmVar n"
| "tm_ty_subst k S (TmApp M N) =
    TmApp (tm_ty_subst k S M) (tm_ty_subst k S N)"
| "tm_ty_subst k S (TmLam A M) =
    TmLam (ty_subst k S A) (tm_ty_subst k S M)"
| "tm_ty_subst k S (TmTAbs M) =
    TmTAbs (tm_ty_subst (Suc k) (ty_shift 0 S) M)"
| "tm_ty_subst k S (TmTApp M A) =
    TmTApp (tm_ty_subst k S M) (ty_subst k S A)"

definition tm_ty_subst0 :: "dty  dtm  dtm"
where
  "tm_ty_subst0 S M = tm_ty_subst 0 S M"

definition ty_env_cons :: "'a  (nat  'a)  nat  'a"
where
  "ty_env_cons C ρ n = (case n of 0  C | Suc k  ρ k)"

definition tm_env_cons :: "dtm  (nat  dtm)  nat  dtm"
where
  "tm_env_cons N δ n = (case n of 0  N | Suc k  δ k)"

definition tm_env_shift :: "(nat  dtm)  nat  dtm"
where
  "tm_env_shift δ n =
    (case n of 0  TmVar 0 | Suc k  tm_shift 0 (δ k))"

fun tm_subst_env :: "(nat  dtm)  dtm  dtm" where
  "tm_subst_env δ (TmVar k) = δ k"
| "tm_subst_env δ (TmApp M N) =
    TmApp (tm_subst_env δ M) (tm_subst_env δ N)"
| "tm_subst_env δ (TmLam A M) =
    TmLam A (tm_subst_env (tm_env_shift δ) M)"
| "tm_subst_env δ (TmTAbs M) = TmTAbs (tm_subst_env δ M)"
| "tm_subst_env δ (TmTApp M A) =
    TmTApp (tm_subst_env δ M) A"

inductive wf_ty :: "nat  dty  bool" where
  wf_var: "n < k  wf_ty k (TyVar n)"
| wf_arr: "wf_ty k A; wf_ty k B 
    wf_ty k (TyArr A B)"
| wf_all: "wf_ty (Suc k) A  wf_ty k (TyAll A)"

inductive ctx_mem :: "dty list  nat  dty  bool" where
  ctx_zero: "ctx_mem (A # Γ) 0 A"
| ctx_suc: "ctx_mem Γ k A  ctx_mem (B # Γ) (Suc k) A"

inductive typing :: "nat  dty list  dtm  dty  bool"
  (‹_ ; _  _ : _› [60,60,60,60] 60) where
  ty_var: "ctx_mem Γ n A  typing k Γ (TmVar n) A"
| ty_app: "typing k Γ M (TyArr A B); typing k Γ N A
     typing k Γ (TmApp M N) B"
| ty_lam: "wf_ty k A; typing k (A # Γ) M B
     typing k Γ (TmLam A M) (TyArr A B)"
| ty_tabs: "typing (Suc k) (map (ty_shift 0) Γ) M B
     typing k Γ (TmTAbs M) (TyAll B)"
| ty_tapp: "typing k Γ M (TyAll B); wf_ty k A
     typing k Γ (TmTApp M A) (ty_subst0 A B)"

inductive beta :: "dtm  dtm  bool"
  (‹_ β _› [80,80] 80) where
  beta_appL: "M β M' 
    TmApp M N β TmApp M' N"
| beta_appR: "N β N' 
    TmApp M N β TmApp M N'"
| beta_lam: "M β M' 
    TmLam A M β TmLam A M'"
| beta_tabs: "M β M' 
    TmTAbs M β TmTAbs M'"
| beta_tapp: "M β M' 
    TmTApp M A β TmTApp M' A"
| beta_term: "TmApp (TmLam A M) N β tm_subst0 N M"
| beta_type: "TmTApp (TmTAbs M) A β tm_ty_subst0 A M"

inductive SN :: "dtm  bool" where
  SN_intro: "(M'. M β M'  SN M')  SN M"

end