src/HOL/Quotient_Examples/Lift_FSet.thy
author traytel
Wed, 13 Mar 2013 13:23:16 +0100
changeset 52547 f0865a641e76
parent 52513 8e38ff09864a
child 52548 deb59caefdb3
permissions -rw-r--r--
BNF uses fset defined via Lifting/Transfer rather than Quotient
huffman@48531
     1
(*  Title:      HOL/Quotient_Examples/Lift_FSet.thy
huffman@48531
     2
    Author:     Brian Huffman, TU Munich
huffman@48531
     3
*)
huffman@48531
     4
huffman@48531
     5
header {* Lifting and transfer with a finite set type *}
huffman@48531
     6
huffman@48531
     7
theory Lift_FSet
huffman@48531
     8
imports "~~/src/HOL/Library/Quotient_List"
huffman@48531
     9
begin
huffman@48531
    10
huffman@48531
    11
subsection {* Equivalence relation and quotient type definition *}
huffman@48531
    12
huffman@48531
    13
definition list_eq :: "'a list \<Rightarrow> 'a list \<Rightarrow> bool"
huffman@48531
    14
  where [simp]: "list_eq xs ys \<longleftrightarrow> set xs = set ys"
huffman@48531
    15
huffman@48531
    16
lemma reflp_list_eq: "reflp list_eq"
huffman@48531
    17
  unfolding reflp_def by simp
huffman@48531
    18
huffman@48531
    19
lemma symp_list_eq: "symp list_eq"
huffman@48531
    20
  unfolding symp_def by simp
huffman@48531
    21
huffman@48531
    22
lemma transp_list_eq: "transp list_eq"
huffman@48531
    23
  unfolding transp_def by simp
huffman@48531
    24
huffman@48531
    25
lemma equivp_list_eq: "equivp list_eq"
huffman@48531
    26
  by (intro equivpI reflp_list_eq symp_list_eq transp_list_eq)
huffman@48531
    27
kuncar@52513
    28
lemma list_eq_transfer [transfer_rule]:
kuncar@52513
    29
  assumes [transfer_rule]: "bi_unique A"
kuncar@52513
    30
  shows "(list_all2 A ===> list_all2 A ===> op =) list_eq list_eq"
kuncar@52513
    31
  unfolding list_eq_def [abs_def] by transfer_prover
kuncar@52513
    32
kuncar@52513
    33
quotient_type 'a fset = "'a list" / "list_eq" parametric list_eq_transfer
huffman@48531
    34
  by (rule equivp_list_eq)
huffman@48531
    35
huffman@48531
    36
subsection {* Lifted constant definitions *}
huffman@48531
    37
traytel@52547
    38
lift_definition fnil :: "'a fset" ("{||}") is "[]" parametric Nil_transfer
huffman@48531
    39
  by simp
huffman@48531
    40
kuncar@52513
    41
lift_definition fcons :: "'a \<Rightarrow> 'a fset \<Rightarrow> 'a fset" is Cons parametric Cons_transfer
huffman@48531
    42
  by simp
huffman@48531
    43
kuncar@52513
    44
lift_definition fappend :: "'a fset \<Rightarrow> 'a fset \<Rightarrow> 'a fset" is append parametric append_transfer
huffman@48531
    45
  by simp
huffman@48531
    46
kuncar@52513
    47
lift_definition fmap :: "('a \<Rightarrow> 'b) \<Rightarrow> 'a fset \<Rightarrow> 'b fset" is map parametric map_transfer
huffman@48531
    48
  by simp
huffman@48531
    49
kuncar@52513
    50
lift_definition ffilter :: "('a \<Rightarrow> bool) \<Rightarrow> 'a fset \<Rightarrow> 'a fset" is filter parametric filter_transfer
huffman@48531
    51
  by simp
huffman@48531
    52
kuncar@52513
    53
lift_definition fset :: "'a fset \<Rightarrow> 'a set" is set parametric set_transfer
huffman@48531
    54
  by simp
huffman@48531
    55
huffman@48531
    56
text {* Constants with nested types (like concat) yield a more
huffman@48531
    57
  complicated proof obligation. *}
huffman@48531
    58
huffman@48531
    59
lemma list_all2_cr_fset:
huffman@48531
    60
  "list_all2 cr_fset xs ys \<longleftrightarrow> map abs_fset xs = ys"
huffman@48531
    61
  unfolding cr_fset_def
huffman@48531
    62
  apply safe
huffman@48531
    63
  apply (erule list_all2_induct, simp, simp)
huffman@48531
    64
  apply (simp add: list_all2_map2 List.list_all2_refl)
huffman@48531
    65
  done
huffman@48531
    66
huffman@48531
    67
lemma abs_fset_eq_iff: "abs_fset xs = abs_fset ys \<longleftrightarrow> list_eq xs ys"
huffman@48531
    68
  using Quotient_rel [OF Quotient_fset] by simp
huffman@48531
    69
kuncar@52513
    70
lift_definition fconcat :: "'a fset fset \<Rightarrow> 'a fset" is concat parametric concat_transfer
huffman@48531
    71
proof -
huffman@48531
    72
  fix xss yss :: "'a list list"
huffman@48531
    73
  assume "(list_all2 cr_fset OO list_eq OO (list_all2 cr_fset)\<inverse>\<inverse>) xss yss"
huffman@48531
    74
  then obtain uss vss where
huffman@48531
    75
    "list_all2 cr_fset xss uss" and "list_eq uss vss" and
huffman@48531
    76
    "list_all2 cr_fset yss vss" by clarsimp
huffman@48531
    77
  hence "list_eq (map abs_fset xss) (map abs_fset yss)"
huffman@48531
    78
    unfolding list_all2_cr_fset by simp
huffman@48531
    79
  thus "list_eq (concat xss) (concat yss)"
huffman@48531
    80
    apply (simp add: set_eq_iff image_def)
huffman@48531
    81
    apply safe
huffman@48531
    82
    apply (rename_tac xs, drule_tac x="abs_fset xs" in spec)
huffman@48531
    83
    apply (drule iffD1, fast, clarsimp simp add: abs_fset_eq_iff, fast)
huffman@48531
    84
    apply (rename_tac xs, drule_tac x="abs_fset xs" in spec)
huffman@48531
    85
    apply (drule iffD2, fast, clarsimp simp add: abs_fset_eq_iff, fast)
huffman@48531
    86
    done
huffman@48531
    87
qed
huffman@48531
    88
traytel@52547
    89
syntax
traytel@52547
    90
  "_insert_fset"     :: "args => 'a fset"  ("{|(_)|}")
traytel@52547
    91
traytel@52547
    92
translations
traytel@52547
    93
  "{|x, xs|}" == "CONST fcons x {|xs|}"
traytel@52547
    94
  "{|x|}"     == "CONST fcons x {||}"
traytel@52547
    95
traytel@52547
    96
lift_definition fset_member :: "'a \<Rightarrow> 'a fset \<Rightarrow> bool" (infix "|\<in>|" 50) is "\<lambda>x xs. x \<in> set xs"
traytel@52547
    97
   by simp
traytel@52547
    98
traytel@52547
    99
abbreviation notin_fset :: "'a \<Rightarrow> 'a fset \<Rightarrow> bool" (infix "|\<notin>|" 50) where
traytel@52547
   100
  "x |\<notin>| S \<equiv> \<not> (x |\<in>| S)"
traytel@52547
   101
traytel@52547
   102
lemma fset_member_fmap[simp]: "a |\<in>| fmap f X = (\<exists>b. b |\<in>| X \<and> a = f b)"
traytel@52547
   103
  by transfer auto
traytel@52547
   104
kuncar@48952
   105
text {* We can export code: *}
kuncar@48952
   106
kuncar@48952
   107
export_code fnil fcons fappend fmap ffilter fset in SML
kuncar@48952
   108
huffman@48531
   109
subsection {* Using transfer with type @{text "fset"} *}
huffman@48531
   110
huffman@48531
   111
text {* The correspondence relation @{text "cr_fset"} can only relate
huffman@48531
   112
  @{text "list"} and @{text "fset"} types with the same element type.
huffman@48531
   113
  To relate nested types like @{text "'a list list"} and
huffman@48531
   114
  @{text "'a fset fset"}, we define a parameterized version of the
kuncar@51242
   115
  correspondence relation, @{text "pcr_fset"}. *}
huffman@48531
   116
kuncar@51242
   117
thm pcr_fset_def
huffman@48531
   118
huffman@48531
   119
subsection {* Transfer examples *}
huffman@48531
   120
huffman@48531
   121
text {* The @{text "transfer"} method replaces equality on @{text
huffman@48531
   122
  "fset"} with the @{text "list_eq"} relation on lists, which is
huffman@48531
   123
  logically equivalent. *}
huffman@48531
   124
huffman@48531
   125
lemma "fmap f (fmap g xs) = fmap (f \<circ> g) xs"
huffman@48531
   126
  apply transfer
huffman@48531
   127
  apply simp
huffman@48531
   128
  done
huffman@48531
   129
huffman@48531
   130
text {* The @{text "transfer'"} variant can replace equality on @{text
huffman@48531
   131
  "fset"} with equality on @{text "list"}, which is logically stronger
huffman@48531
   132
  but sometimes more convenient. *}
huffman@48531
   133
huffman@48531
   134
lemma "fmap f (fmap g xs) = fmap (f \<circ> g) xs"
huffman@48531
   135
  apply transfer'
huffman@48531
   136
  apply (rule map_map)
huffman@48531
   137
  done
huffman@48531
   138
huffman@48531
   139
lemma "ffilter p (fmap f xs) = fmap f (ffilter (p \<circ> f) xs)"
huffman@48531
   140
  apply transfer'
huffman@48531
   141
  apply (rule filter_map)
huffman@48531
   142
  done
huffman@48531
   143
huffman@48531
   144
lemma "ffilter p (ffilter q xs) = ffilter (\<lambda>x. q x \<and> p x) xs"
huffman@48531
   145
  apply transfer'
huffman@48531
   146
  apply (rule filter_filter)
huffman@48531
   147
  done
huffman@48531
   148
huffman@48531
   149
lemma "fset (fcons x xs) = insert x (fset xs)"
huffman@48531
   150
  apply transfer
huffman@48531
   151
  apply (rule set.simps)
huffman@48531
   152
  done
huffman@48531
   153
huffman@48531
   154
lemma "fset (fappend xs ys) = fset xs \<union> fset ys"
huffman@48531
   155
  apply transfer
huffman@48531
   156
  apply (rule set_append)
huffman@48531
   157
  done
huffman@48531
   158
huffman@48531
   159
lemma "fset (fconcat xss) = (\<Union>xs\<in>fset xss. fset xs)"
huffman@48531
   160
  apply transfer
huffman@48531
   161
  apply (rule set_concat)
huffman@48531
   162
  done
huffman@48531
   163
huffman@48531
   164
lemma "\<forall>x\<in>fset xs. f x = g x \<Longrightarrow> fmap f xs = fmap g xs"
huffman@48531
   165
  apply transfer
huffman@48531
   166
  apply (simp cong: map_cong del: set_map)
huffman@48531
   167
  done
huffman@48531
   168
huffman@48531
   169
lemma "fnil = fconcat xss \<longleftrightarrow> (\<forall>xs\<in>fset xss. xs = fnil)"
huffman@48531
   170
  apply transfer
huffman@48531
   171
  apply simp
huffman@48531
   172
  done
huffman@48531
   173
huffman@48531
   174
lemma "fconcat (fmap (\<lambda>x. fcons x fnil) xs) = xs"
huffman@48531
   175
  apply transfer'
huffman@48531
   176
  apply simp
huffman@48531
   177
  done
huffman@48531
   178
huffman@48531
   179
lemma concat_map_concat: "concat (map concat xsss) = concat (concat xsss)"
huffman@48531
   180
  by (induct xsss, simp_all)
huffman@48531
   181
huffman@48531
   182
lemma "fconcat (fmap fconcat xss) = fconcat (fconcat xss)"
huffman@48531
   183
  apply transfer'
huffman@48531
   184
  apply (rule concat_map_concat)
huffman@48531
   185
  done
huffman@48531
   186
huffman@48531
   187
end