src/HOL/Library/Coinductive_List.thy
changeset 20820 58693343905f
parent 20802 1b43d9184bf5
child 21404 eb85850d3eb7
equal deleted inserted replaced
20819:cb6ae81dd0be 20820:58693343905f
    10 begin
    10 begin
    11 
    11 
    12 subsection {* List constructors over the datatype universe *}
    12 subsection {* List constructors over the datatype universe *}
    13 
    13 
    14 definition
    14 definition
    15   "NIL = Datatype_Universe.In0 (Datatype_Universe.Numb 0)"
    15   "NIL = Datatype.In0 (Datatype.Numb 0)"
    16   "CONS M N = Datatype_Universe.In1 (Datatype_Universe.Scons M N)"
    16   "CONS M N = Datatype.In1 (Datatype.Scons M N)"
    17 
    17 
    18 lemma CONS_not_NIL [iff]: "CONS M N \<noteq> NIL"
    18 lemma CONS_not_NIL [iff]: "CONS M N \<noteq> NIL"
    19   and NIL_not_CONS [iff]: "NIL \<noteq> CONS M N"
    19   and NIL_not_CONS [iff]: "NIL \<noteq> CONS M N"
    20   and CONS_inject [iff]: "(CONS K M) = (CONS L N) = (K = L \<and> M = N)"
    20   and CONS_inject [iff]: "(CONS K M) = (CONS L N) = (K = L \<and> M = N)"
    21   by (simp_all add: NIL_def CONS_def)
    21   by (simp_all add: NIL_def CONS_def)
    26 lemma CONS_UN1: "CONS M (\<Union>x. f x) = (\<Union>x. CONS M (f x))"
    26 lemma CONS_UN1: "CONS M (\<Union>x. f x) = (\<Union>x. CONS M (f x))"
    27     -- {* A continuity result? *}
    27     -- {* A continuity result? *}
    28   by (simp add: CONS_def In1_UN1 Scons_UN1_y)
    28   by (simp add: CONS_def In1_UN1 Scons_UN1_y)
    29 
    29 
    30 definition
    30 definition
    31   "List_case c h = Datatype_Universe.Case (\<lambda>_. c) (Datatype_Universe.Split h)"
    31   "List_case c h = Datatype.Case (\<lambda>_. c) (Datatype.Split h)"
    32 
    32 
    33 lemma List_case_NIL [simp]: "List_case c h NIL = c"
    33 lemma List_case_NIL [simp]: "List_case c h NIL = c"
    34   and List_case_CONS [simp]: "List_case c h (CONS M N) = h M N"
    34   and List_case_CONS [simp]: "List_case c h (CONS M N) = h M N"
    35   by (simp_all add: List_case_def NIL_def CONS_def)
    35   by (simp_all add: List_case_def NIL_def CONS_def)
    36 
    36 
    37 
    37 
    38 subsection {* Corecursive lists *}
    38 subsection {* Corecursive lists *}
    39 
    39 
    40 consts
    40 consts
    41   LList  :: "'a Datatype_Universe.item set \<Rightarrow> 'a Datatype_Universe.item set"
    41   LList  :: "'a Datatype.item set \<Rightarrow> 'a Datatype.item set"
    42 
    42 
    43 coinductive "LList A"
    43 coinductive "LList A"
    44   intros
    44   intros
    45     NIL [intro]:  "NIL \<in> LList A"
    45     NIL [intro]:  "NIL \<in> LList A"
    46     CONS [intro]: "a \<in> A \<Longrightarrow> M \<in> LList A \<Longrightarrow> CONS a M \<in> LList A"
    46     CONS [intro]: "a \<in> A \<Longrightarrow> M \<in> LList A \<Longrightarrow> CONS a M \<in> LList A"
    48 lemma LList_mono: "A \<subseteq> B \<Longrightarrow> LList A \<subseteq> LList B"
    48 lemma LList_mono: "A \<subseteq> B \<Longrightarrow> LList A \<subseteq> LList B"
    49     -- {* This justifies using @{text LList} in other recursive type definitions. *}
    49     -- {* This justifies using @{text LList} in other recursive type definitions. *}
    50   unfolding LList.defs by (blast intro!: gfp_mono)
    50   unfolding LList.defs by (blast intro!: gfp_mono)
    51 
    51 
    52 consts
    52 consts
    53   LList_corec_aux :: "nat \<Rightarrow> ('a \<Rightarrow> ('b Datatype_Universe.item \<times> 'a) option) \<Rightarrow>
    53   LList_corec_aux :: "nat \<Rightarrow> ('a \<Rightarrow> ('b Datatype.item \<times> 'a) option) \<Rightarrow>
    54     'a \<Rightarrow> 'b Datatype_Universe.item"
    54     'a \<Rightarrow> 'b Datatype.item"
    55 primrec
    55 primrec
    56   "LList_corec_aux 0 f x = {}"
    56   "LList_corec_aux 0 f x = {}"
    57   "LList_corec_aux (Suc k) f x =
    57   "LList_corec_aux (Suc k) f x =
    58     (case f x of
    58     (case f x of
    59       None \<Rightarrow> NIL
    59       None \<Rightarrow> NIL
   115 
   115 
   116 
   116 
   117 subsection {* Abstract type definition *}
   117 subsection {* Abstract type definition *}
   118 
   118 
   119 typedef 'a llist =
   119 typedef 'a llist =
   120   "LList (range Datatype_Universe.Leaf) :: 'a Datatype_Universe.item set"
   120   "LList (range Datatype.Leaf) :: 'a Datatype.item set"
   121 proof
   121 proof
   122   show "NIL \<in> ?llist" ..
   122   show "NIL \<in> ?llist" ..
   123 qed
   123 qed
   124 
   124 
   125 lemma NIL_type: "NIL \<in> llist"
   125 lemma NIL_type: "NIL \<in> llist"
   126   unfolding llist_def by (rule LList.NIL)
   126   unfolding llist_def by (rule LList.NIL)
   127 
   127 
   128 lemma CONS_type: "a \<in> range Datatype_Universe.Leaf \<Longrightarrow>
   128 lemma CONS_type: "a \<in> range Datatype.Leaf \<Longrightarrow>
   129     M \<in> llist \<Longrightarrow> CONS a M \<in> llist"
   129     M \<in> llist \<Longrightarrow> CONS a M \<in> llist"
   130   unfolding llist_def by (rule LList.CONS)
   130   unfolding llist_def by (rule LList.CONS)
   131 
   131 
   132 lemma llistI: "x \<in> LList (range Datatype_Universe.Leaf) \<Longrightarrow> x \<in> llist"
   132 lemma llistI: "x \<in> LList (range Datatype.Leaf) \<Longrightarrow> x \<in> llist"
   133   by (simp add: llist_def)
   133   by (simp add: llist_def)
   134 
   134 
   135 lemma llistD: "x \<in> llist \<Longrightarrow> x \<in> LList (range Datatype_Universe.Leaf)"
   135 lemma llistD: "x \<in> llist \<Longrightarrow> x \<in> LList (range Datatype.Leaf)"
   136   by (simp add: llist_def)
   136   by (simp add: llist_def)
   137 
   137 
   138 lemma Rep_llist_UNIV: "Rep_llist x \<in> LList UNIV"
   138 lemma Rep_llist_UNIV: "Rep_llist x \<in> LList UNIV"
   139 proof -
   139 proof -
   140   have "Rep_llist x \<in> llist" by (rule Rep_llist)
   140   have "Rep_llist x \<in> llist" by (rule Rep_llist)
   141   then have "Rep_llist x \<in> LList (range Datatype_Universe.Leaf)"
   141   then have "Rep_llist x \<in> LList (range Datatype.Leaf)"
   142     by (simp add: llist_def)
   142     by (simp add: llist_def)
   143   also have "\<dots> \<subseteq> LList UNIV" by (rule LList_mono) simp
   143   also have "\<dots> \<subseteq> LList UNIV" by (rule LList_mono) simp
   144   finally show ?thesis .
   144   finally show ?thesis .
   145 qed
   145 qed
   146 
   146 
   147 definition
   147 definition
   148   "LNil = Abs_llist NIL"
   148   "LNil = Abs_llist NIL"
   149   "LCons x xs = Abs_llist (CONS (Datatype_Universe.Leaf x) (Rep_llist xs))"
   149   "LCons x xs = Abs_llist (CONS (Datatype.Leaf x) (Rep_llist xs))"
   150 
   150 
   151 lemma LCons_not_LNil [iff]: "LCons x xs \<noteq> LNil"
   151 lemma LCons_not_LNil [iff]: "LCons x xs \<noteq> LNil"
   152   apply (simp add: LNil_def LCons_def)
   152   apply (simp add: LNil_def LCons_def)
   153   apply (subst Abs_llist_inject)
   153   apply (subst Abs_llist_inject)
   154     apply (auto intro: NIL_type CONS_type Rep_llist)
   154     apply (auto intro: NIL_type CONS_type Rep_llist)
   165 
   165 
   166 lemma Rep_llist_LNil: "Rep_llist LNil = NIL"
   166 lemma Rep_llist_LNil: "Rep_llist LNil = NIL"
   167   by (simp add: LNil_def add: Abs_llist_inverse NIL_type)
   167   by (simp add: LNil_def add: Abs_llist_inverse NIL_type)
   168 
   168 
   169 lemma Rep_llist_LCons: "Rep_llist (LCons x l) =
   169 lemma Rep_llist_LCons: "Rep_llist (LCons x l) =
   170     CONS (Datatype_Universe.Leaf x) (Rep_llist l)"
   170     CONS (Datatype.Leaf x) (Rep_llist l)"
   171   by (simp add: LCons_def Abs_llist_inverse CONS_type Rep_llist)
   171   by (simp add: LCons_def Abs_llist_inverse CONS_type Rep_llist)
   172 
   172 
   173 lemma llist_cases [cases type: llist]:
   173 lemma llist_cases [cases type: llist]:
   174   obtains
   174   obtains
   175     (LNil) "l = LNil"
   175     (LNil) "l = LNil"
   176   | (LCons) x l' where "l = LCons x l'"
   176   | (LCons) x l' where "l = LCons x l'"
   177 proof (cases l)
   177 proof (cases l)
   178   case (Abs_llist L)
   178   case (Abs_llist L)
   179   from `L \<in> llist` have "L \<in> LList (range Datatype_Universe.Leaf)" by (rule llistD)
   179   from `L \<in> llist` have "L \<in> LList (range Datatype.Leaf)" by (rule llistD)
   180   then show ?thesis
   180   then show ?thesis
   181   proof cases
   181   proof cases
   182     case NIL
   182     case NIL
   183     with Abs_llist have "l = LNil" by (simp add: LNil_def)
   183     with Abs_llist have "l = LNil" by (simp add: LNil_def)
   184     with LNil show ?thesis .
   184     with LNil show ?thesis .
   193 qed
   193 qed
   194 
   194 
   195 
   195 
   196 definition
   196 definition
   197   "llist_case c d l =
   197   "llist_case c d l =
   198     List_case c (\<lambda>x y. d (inv Datatype_Universe.Leaf x) (Abs_llist y)) (Rep_llist l)"
   198     List_case c (\<lambda>x y. d (inv Datatype.Leaf x) (Abs_llist y)) (Rep_llist l)"
   199 
   199 
   200 syntax  (* FIXME? *)
   200 syntax  (* FIXME? *)
   201   LNil :: logic
   201   LNil :: logic
   202   LCons :: logic
   202   LCons :: logic
   203 translations
   203 translations
   215 definition
   215 definition
   216   "llist_corec a f =
   216   "llist_corec a f =
   217     Abs_llist (LList_corec a
   217     Abs_llist (LList_corec a
   218       (\<lambda>z.
   218       (\<lambda>z.
   219         case f z of None \<Rightarrow> None
   219         case f z of None \<Rightarrow> None
   220         | Some (v, w) \<Rightarrow> Some (Datatype_Universe.Leaf v, w)))"
   220         | Some (v, w) \<Rightarrow> Some (Datatype.Leaf v, w)))"
   221 
   221 
   222 lemma LList_corec_type2:
   222 lemma LList_corec_type2:
   223   "LList_corec a
   223   "LList_corec a
   224     (\<lambda>z. case f z of None \<Rightarrow> None
   224     (\<lambda>z. case f z of None \<Rightarrow> None
   225       | Some (v, w) \<Rightarrow> Some (Datatype_Universe.Leaf v, w)) \<in> llist"
   225       | Some (v, w) \<Rightarrow> Some (Datatype.Leaf v, w)) \<in> llist"
   226   (is "?corec a \<in> _")
   226   (is "?corec a \<in> _")
   227 proof (unfold llist_def)
   227 proof (unfold llist_def)
   228   let "LList_corec a ?g" = "?corec a"
   228   let "LList_corec a ?g" = "?corec a"
   229   have "?corec a \<in> {?corec x | x. True}" by blast
   229   have "?corec a \<in> {?corec x | x. True}" by blast
   230   then show "?corec a \<in> LList (range Datatype_Universe.Leaf)"
   230   then show "?corec a \<in> LList (range Datatype.Leaf)"
   231   proof coinduct
   231   proof coinduct
   232     case (LList L)
   232     case (LList L)
   233     then obtain x where L: "L = ?corec x" by blast
   233     then obtain x where L: "L = ?corec x" by blast
   234     show ?case
   234     show ?case
   235     proof (cases "f x")
   235     proof (cases "f x")
   239       with L have ?NIL by simp
   239       with L have ?NIL by simp
   240       then show ?thesis ..
   240       then show ?thesis ..
   241     next
   241     next
   242       case (Some p)
   242       case (Some p)
   243       then have "?corec x =
   243       then have "?corec x =
   244           CONS (Datatype_Universe.Leaf (fst p)) (?corec (snd p))"
   244           CONS (Datatype.Leaf (fst p)) (?corec (snd p))"
   245         by (simp add: split_def LList_corec)
   245         by (simp add: split_def LList_corec)
   246       with L have ?CONS by auto
   246       with L have ?CONS by auto
   247       then show ?thesis ..
   247       then show ?thesis ..
   248     qed
   248     qed
   249   qed
   249   qed
   261 
   261 
   262   let "?corec a" = "llist_corec a f"
   262   let "?corec a" = "llist_corec a f"
   263   let "?rep_corec a" =
   263   let "?rep_corec a" =
   264     "LList_corec a
   264     "LList_corec a
   265       (\<lambda>z. case f z of None \<Rightarrow> None
   265       (\<lambda>z. case f z of None \<Rightarrow> None
   266         | Some (v, w) \<Rightarrow> Some (Datatype_Universe.Leaf v, w))"
   266         | Some (v, w) \<Rightarrow> Some (Datatype.Leaf v, w))"
   267 
   267 
   268   have "?corec a = Abs_llist (?rep_corec a)"
   268   have "?corec a = Abs_llist (?rep_corec a)"
   269     by (simp only: llist_corec_def)
   269     by (simp only: llist_corec_def)
   270   also from Some have "?rep_corec a =
   270   also from Some have "?rep_corec a =
   271       CONS (Datatype_Universe.Leaf (fst p)) (?rep_corec (snd p))"
   271       CONS (Datatype.Leaf (fst p)) (?rep_corec (snd p))"
   272     by (simp add: split_def LList_corec)
   272     by (simp add: split_def LList_corec)
   273   also have "?rep_corec (snd p) = Rep_llist (?corec (snd p))"
   273   also have "?rep_corec (snd p) = Rep_llist (?corec (snd p))"
   274     by (simp only: llist_corec_def Abs_llist_inverse LList_corec_type2)
   274     by (simp only: llist_corec_def Abs_llist_inverse LList_corec_type2)
   275   finally have "?corec a = LCons (fst p) (?corec (snd p))"
   275   finally have "?corec a = LCons (fst p) (?corec (snd p))"
   276     by (simp only: LCons_def)
   276     by (simp only: LCons_def)
   279 
   279 
   280 
   280 
   281 subsection {* Equality as greatest fixed-point; the bisimulation principle. *}
   281 subsection {* Equality as greatest fixed-point; the bisimulation principle. *}
   282 
   282 
   283 consts
   283 consts
   284   EqLList :: "('a Datatype_Universe.item \<times> 'a Datatype_Universe.item) set \<Rightarrow>
   284   EqLList :: "('a Datatype.item \<times> 'a Datatype.item) set \<Rightarrow>
   285     ('a Datatype_Universe.item \<times> 'a Datatype_Universe.item) set"
   285     ('a Datatype.item \<times> 'a Datatype.item) set"
   286 
   286 
   287 coinductive "EqLList r"
   287 coinductive "EqLList r"
   288   intros
   288   intros
   289     EqNIL: "(NIL, NIL) \<in> EqLList r"
   289     EqNIL: "(NIL, NIL) \<in> EqLList r"
   290     EqCONS: "(a, b) \<in> r \<Longrightarrow> (M, N) \<in> EqLList r \<Longrightarrow>
   290     EqCONS: "(a, b) \<in> r \<Longrightarrow> (M, N) \<in> EqLList r \<Longrightarrow>
   291       (CONS a M, CONS b N) \<in> EqLList r"
   291       (CONS a M, CONS b N) \<in> EqLList r"
   292 
   292 
   293 lemma EqLList_unfold:
   293 lemma EqLList_unfold:
   294     "EqLList r = dsum (diag {Datatype_Universe.Numb 0}) (dprod r (EqLList r))"
   294     "EqLList r = dsum (diag {Datatype.Numb 0}) (dprod r (EqLList r))"
   295   by (fast intro!: EqLList.intros [unfolded NIL_def CONS_def]
   295   by (fast intro!: EqLList.intros [unfolded NIL_def CONS_def]
   296            elim: EqLList.cases [unfolded NIL_def CONS_def])
   296            elim: EqLList.cases [unfolded NIL_def CONS_def])
   297 
   297 
   298 lemma EqLList_implies_ntrunc_equality:
   298 lemma EqLList_implies_ntrunc_equality:
   299     "(M, N) \<in> EqLList (diag A) \<Longrightarrow> ntrunc k M = ntrunc k N"
   299     "(M, N) \<in> EqLList (diag A) \<Longrightarrow> ntrunc k M = ntrunc k N"
   610   shows "Lmap (f o g) M = Lmap f (Lmap g M)"  (is "?lhs M = ?rhs M")
   610   shows "Lmap (f o g) M = Lmap f (Lmap g M)"  (is "?lhs M = ?rhs M")
   611 proof -
   611 proof -
   612   have "(?lhs M, ?rhs M) \<in> {(?lhs N, ?rhs N) | N. N \<in> LList A}"
   612   have "(?lhs M, ?rhs M) \<in> {(?lhs N, ?rhs N) | N. N \<in> LList A}"
   613     using M by blast
   613     using M by blast
   614   then show ?thesis
   614   then show ?thesis
   615   proof (coinduct taking: "range (\<lambda>N :: 'a Datatype_Universe.item. N)"
   615   proof (coinduct taking: "range (\<lambda>N :: 'a Datatype.item. N)"
   616       rule: LList_equalityI)
   616       rule: LList_equalityI)
   617     case (EqLList q)
   617     case (EqLList q)
   618     then obtain N where q: "q = (?lhs N, ?rhs N)" and N: "N \<in> LList A" by blast
   618     then obtain N where q: "q = (?lhs N, ?rhs N)" and N: "N \<in> LList A" by blast
   619     from N show ?case
   619     from N show ?case
   620     proof cases
   620     proof cases
   633   assumes M: "M \<in> LList A"
   633   assumes M: "M \<in> LList A"
   634   shows "Lmap (\<lambda>x. x) M = M"  (is "?lmap M = _")
   634   shows "Lmap (\<lambda>x. x) M = M"  (is "?lmap M = _")
   635 proof -
   635 proof -
   636   have "(?lmap M, M) \<in> {(?lmap N, N) | N. N \<in> LList A}" using M by blast
   636   have "(?lmap M, M) \<in> {(?lmap N, N) | N. N \<in> LList A}" using M by blast
   637   then show ?thesis
   637   then show ?thesis
   638   proof (coinduct taking: "range (\<lambda>N :: 'a Datatype_Universe.item. N)"
   638   proof (coinduct taking: "range (\<lambda>N :: 'a Datatype.item. N)"
   639       rule: LList_equalityI)
   639       rule: LList_equalityI)
   640     case (EqLList q)
   640     case (EqLList q)
   641     then obtain N where q: "q = (?lmap N, N)" and N: "N \<in> LList A" by blast
   641     then obtain N where q: "q = (?lmap N, N)" and N: "N \<in> LList A" by blast
   642     from N show ?case
   642     from N show ?case
   643     proof cases
   643     proof cases