Theory CL_Z

(*
 * Title:      Z  
 * Author:     Bertram Felgenhauer (2016)
 * Author:     Julian Nagele (2016)
 * Author:     Vincent van Oostrom (2016)
 * Author:     Christian Sternagel (2016)
 * Maintainer: Bertram Felgenhauer <bertram.felgenhauer@uibk.ac.at>
 * Maintainer: Juilan Nagele <julian.nagele@uibk.ac.at>
 * Maintainer: Christian Sternagel <c.sternagel@gmail.com>
 * License:    BSD
 *)

section ‹Combinatory Logic has the Church-Rosser property›

theory CL_Z imports Z
begin

datatype CL = S | K | I | App CL CL ("` _ _" [999, 999] 999)

inductive_set red :: "CL rel" where
  L: "(t, t')  red  (` t u, ` t' u)  red"
| R: "(u, u')  red  (` t u, ` t u')  red"
| S: "(` ` ` S x y z, ` ` x z ` y z)  red"
| K: "(` ` K x y, x)  red"
| I: "(` I x, x)  red"

lemma App_mono:
  "(t, t')  red*  (u, u')  red*  (` t u, ` t' u')  red*"
proof -
  assume "(t, t')  red*" hence "(` t u, ` t' u)  red*"
    by (induct t' rule: rtrancl_induct) (auto intro: rtrancl_into_rtrancl red.intros)
  moreover assume "(u, u')  red*" hence "(` t' u, ` t' u')  red*"
    by (induct u' rule: rtrancl_induct) (auto intro: rtrancl_into_rtrancl red.intros)
  ultimately show ?thesis by auto
qed

fun bullet_app :: "CL  CL  CL" where
  "bullet_app (` ` S x y) z = ` ` x z ` y z"
| "bullet_app (` K x) y = x"
| "bullet_app I x = x"
| "bullet_app t u = ` t u"

lemma bullet_app_red:
  "(` t u, bullet_app t u)  red="
by (induct t u rule: bullet_app.induct) (auto intro: red.intros)

lemma bullet_app_redsI:
  "(s, ` t u)  red*  (s, bullet_app t u)  red*"
using bullet_app_red[of t u] by auto

lemma bullet_app_redL:
  "(t, t')  red  (bullet_app t u, bullet_app t' u)  red*"
by (induct t u rule: bullet_app.induct)
   (auto 0 6 intro: App_mono bullet_app_redsI elim: red.cases simp only: bullet_app.simps)

lemma bullet_app_redR:
  "(u, u')  red  (bullet_app t u, bullet_app t u')  red*"
by (induct t u rule: bullet_app.induct) (auto intro: App_mono)

lemma bullet_app_mono:
  assumes "(t, t')  red*" "(u, u')  red*" shows "(bullet_app t u, bullet_app t' u')  red*"
proof -
  have "(bullet_app t u, bullet_app t' u)  red*" using assms(1)
    by (induct t' rule: rtrancl_induct) (auto intro: rtrancl_trans bullet_app_redL)
  moreover have "(bullet_app t' u, bullet_app t' u')  red*" using assms(2)
    by (induct u' rule: rtrancl_induct) (auto intro: rtrancl_trans bullet_app_redR)
  ultimately show ?thesis by auto
qed

fun bullet :: "CL  CL" where
  "bullet (` t u) = bullet_app (bullet t) (bullet u)"
| "bullet t = t"

lemma bullet_incremental:
  "(t, bullet t)  red*"
by (induct t rule: bullet.induct) (auto intro: App_mono bullet_app_redsI)

interpretation CL:z_property bullet red
proof (unfold_locales, intro conjI)
  fix t u assume "(t, u)  red" thus "(u, bullet t)  red*"
  proof (induct t arbitrary: u rule: bullet.induct)
    case (1 t1 t2) show ?case using 1(3)
      by (cases) (auto intro: 1 App_mono bullet_app_redsI bullet_incremental)
  qed (auto elim: red.cases)
next
  fix t u assume "(t, u)  red" thus "(bullet t, bullet u)  red*"
    by (induct t u rule: red.induct) (auto intro: App_mono bullet_app_mono bullet_app_redsI)
qed

lemmas CR_red = CL.CR

end