1 (* Title: HOL/HOLCF/ex/Pattern_Match.thy |
1 (* Title: HOL/HOLCF/ex/Pattern_Match.thy |
2 Author: Brian Huffman |
2 Author: Brian Huffman |
3 *) |
3 *) |
4 |
4 |
5 section {* An experimental pattern-matching notation *} |
5 section \<open>An experimental pattern-matching notation\<close> |
6 |
6 |
7 theory Pattern_Match |
7 theory Pattern_Match |
8 imports HOLCF |
8 imports HOLCF |
9 begin |
9 begin |
10 |
10 |
11 default_sort pcpo |
11 default_sort pcpo |
12 |
12 |
13 text {* FIXME: Find a proper way to un-hide constants. *} |
13 text \<open>FIXME: Find a proper way to un-hide constants.\<close> |
14 |
14 |
15 abbreviation fail :: "'a match" |
15 abbreviation fail :: "'a match" |
16 where "fail \<equiv> Fixrec.fail" |
16 where "fail \<equiv> Fixrec.fail" |
17 |
17 |
18 abbreviation succeed :: "'a \<rightarrow> 'a match" |
18 abbreviation succeed :: "'a \<rightarrow> 'a match" |
19 where "succeed \<equiv> Fixrec.succeed" |
19 where "succeed \<equiv> Fixrec.succeed" |
20 |
20 |
21 abbreviation run :: "'a match \<rightarrow> 'a" |
21 abbreviation run :: "'a match \<rightarrow> 'a" |
22 where "run \<equiv> Fixrec.run" |
22 where "run \<equiv> Fixrec.run" |
23 |
23 |
24 subsection {* Fatbar combinator *} |
24 subsection \<open>Fatbar combinator\<close> |
25 |
25 |
26 definition |
26 definition |
27 fatbar :: "('a \<rightarrow> 'b match) \<rightarrow> ('a \<rightarrow> 'b match) \<rightarrow> ('a \<rightarrow> 'b match)" where |
27 fatbar :: "('a \<rightarrow> 'b match) \<rightarrow> ('a \<rightarrow> 'b match) \<rightarrow> ('a \<rightarrow> 'b match)" where |
28 "fatbar = (\<Lambda> a b x. a\<cdot>x +++ b\<cdot>x)" |
28 "fatbar = (\<Lambda> a b x. a\<cdot>x +++ b\<cdot>x)" |
29 |
29 |
51 lemma run_fatbar3: "m\<cdot>x = succeed\<cdot>y \<Longrightarrow> run\<cdot>((m \<parallel> ms)\<cdot>x) = y" |
51 lemma run_fatbar3: "m\<cdot>x = succeed\<cdot>y \<Longrightarrow> run\<cdot>((m \<parallel> ms)\<cdot>x) = y" |
52 by (simp add: fatbar_def) |
52 by (simp add: fatbar_def) |
53 |
53 |
54 lemmas run_fatbar_simps [simp] = run_fatbar1 run_fatbar2 run_fatbar3 |
54 lemmas run_fatbar_simps [simp] = run_fatbar1 run_fatbar2 run_fatbar3 |
55 |
55 |
56 subsection {* Bind operator for match monad *} |
56 subsection \<open>Bind operator for match monad\<close> |
57 |
57 |
58 definition match_bind :: "'a match \<rightarrow> ('a \<rightarrow> 'b match) \<rightarrow> 'b match" where |
58 definition match_bind :: "'a match \<rightarrow> ('a \<rightarrow> 'b match) \<rightarrow> 'b match" where |
59 "match_bind = (\<Lambda> m k. sscase\<cdot>(\<Lambda> _. fail)\<cdot>(fup\<cdot>k)\<cdot>(Rep_match m))" |
59 "match_bind = (\<Lambda> m k. sscase\<cdot>(\<Lambda> _. fail)\<cdot>(fup\<cdot>k)\<cdot>(Rep_match m))" |
60 |
60 |
61 lemma match_bind_simps [simp]: |
61 lemma match_bind_simps [simp]: |
64 "match_bind\<cdot>(succeed\<cdot>x)\<cdot>k = k\<cdot>x" |
64 "match_bind\<cdot>(succeed\<cdot>x)\<cdot>k = k\<cdot>x" |
65 unfolding match_bind_def fail_def succeed_def |
65 unfolding match_bind_def fail_def succeed_def |
66 by (simp_all add: cont_Rep_match cont_Abs_match |
66 by (simp_all add: cont_Rep_match cont_Abs_match |
67 Rep_match_strict Abs_match_inverse) |
67 Rep_match_strict Abs_match_inverse) |
68 |
68 |
69 subsection {* Case branch combinator *} |
69 subsection \<open>Case branch combinator\<close> |
70 |
70 |
71 definition |
71 definition |
72 branch :: "('a \<rightarrow> 'b match) \<Rightarrow> ('b \<rightarrow> 'c) \<rightarrow> ('a \<rightarrow> 'c match)" where |
72 branch :: "('a \<rightarrow> 'b match) \<Rightarrow> ('b \<rightarrow> 'c) \<rightarrow> ('a \<rightarrow> 'c match)" where |
73 "branch p \<equiv> \<Lambda> r x. match_bind\<cdot>(p\<cdot>x)\<cdot>(\<Lambda> y. succeed\<cdot>(r\<cdot>y))" |
73 "branch p \<equiv> \<Lambda> r x. match_bind\<cdot>(p\<cdot>x)\<cdot>(\<Lambda> y. succeed\<cdot>(r\<cdot>y))" |
74 |
74 |
79 by (simp_all add: branch_def) |
79 by (simp_all add: branch_def) |
80 |
80 |
81 lemma branch_succeed [simp]: "branch succeed\<cdot>r\<cdot>x = succeed\<cdot>(r\<cdot>x)" |
81 lemma branch_succeed [simp]: "branch succeed\<cdot>r\<cdot>x = succeed\<cdot>(r\<cdot>x)" |
82 by (simp add: branch_def) |
82 by (simp add: branch_def) |
83 |
83 |
84 subsection {* Cases operator *} |
84 subsection \<open>Cases operator\<close> |
85 |
85 |
86 definition |
86 definition |
87 cases :: "'a match \<rightarrow> 'a::pcpo" where |
87 cases :: "'a match \<rightarrow> 'a::pcpo" where |
88 "cases = Fixrec.run" |
88 "cases = Fixrec.run" |
89 |
89 |
90 text {* rewrite rules for cases *} |
90 text \<open>rewrite rules for cases\<close> |
91 |
91 |
92 lemma cases_strict [simp]: "cases\<cdot>\<bottom> = \<bottom>" |
92 lemma cases_strict [simp]: "cases\<cdot>\<bottom> = \<bottom>" |
93 by (simp add: cases_def) |
93 by (simp add: cases_def) |
94 |
94 |
95 lemma cases_fail [simp]: "cases\<cdot>fail = \<bottom>" |
95 lemma cases_fail [simp]: "cases\<cdot>fail = \<bottom>" |
96 by (simp add: cases_def) |
96 by (simp add: cases_def) |
97 |
97 |
98 lemma cases_succeed [simp]: "cases\<cdot>(succeed\<cdot>x) = x" |
98 lemma cases_succeed [simp]: "cases\<cdot>(succeed\<cdot>x) = x" |
99 by (simp add: cases_def) |
99 by (simp add: cases_def) |
100 |
100 |
101 subsection {* Case syntax *} |
101 subsection \<open>Case syntax\<close> |
102 |
102 |
103 nonterminal Case_pat and Case_syn and Cases_syn |
103 nonterminal Case_pat and Case_syn and Cases_syn |
104 |
104 |
105 syntax |
105 syntax |
106 "_Case_syntax":: "['a, Cases_syn] => 'b" ("(Case _ of/ _)" 10) |
106 "_Case_syntax":: "['a, Cases_syn] => 'b" ("(Case _ of/ _)" 10) |
126 translations |
126 translations |
127 "_Case1 p r" => "CONST branch (_pat p)\<cdot>(_variable p r)" |
127 "_Case1 p r" => "CONST branch (_pat p)\<cdot>(_variable p r)" |
128 "_variable (_args x y) r" => "CONST csplit\<cdot>(_variable x (_variable y r))" |
128 "_variable (_args x y) r" => "CONST csplit\<cdot>(_variable x (_variable y r))" |
129 "_variable _noargs r" => "CONST unit_when\<cdot>r" |
129 "_variable _noargs r" => "CONST unit_when\<cdot>r" |
130 |
130 |
131 parse_translation {* |
131 parse_translation \<open> |
132 (* rewrite (_pat x) => (succeed) *) |
132 (* rewrite (_pat x) => (succeed) *) |
133 (* rewrite (_variable x t) => (Abs_cfun (%x. t)) *) |
133 (* rewrite (_variable x t) => (Abs_cfun (%x. t)) *) |
134 [(@{syntax_const "_pat"}, fn _ => fn _ => Syntax.const @{const_syntax Fixrec.succeed}), |
134 [(@{syntax_const "_pat"}, fn _ => fn _ => Syntax.const @{const_syntax Fixrec.succeed}), |
135 Syntax_Trans.mk_binder_tr (@{syntax_const "_variable"}, @{const_syntax Abs_cfun})]; |
135 Syntax_Trans.mk_binder_tr (@{syntax_const "_variable"}, @{const_syntax Abs_cfun})]; |
136 *} |
136 \<close> |
137 |
137 |
138 text {* Printing Case expressions *} |
138 text \<open>Printing Case expressions\<close> |
139 |
139 |
140 syntax |
140 syntax |
141 "_match" :: "'a" |
141 "_match" :: "'a" |
142 |
142 |
143 print_translation {* |
143 print_translation \<open> |
144 let |
144 let |
145 fun dest_LAM (Const (@{const_syntax Rep_cfun},_) $ Const (@{const_syntax unit_when},_) $ t) = |
145 fun dest_LAM (Const (@{const_syntax Rep_cfun},_) $ Const (@{const_syntax unit_when},_) $ t) = |
146 (Syntax.const @{syntax_const "_noargs"}, t) |
146 (Syntax.const @{syntax_const "_noargs"}, t) |
147 | dest_LAM (Const (@{const_syntax Rep_cfun},_) $ Const (@{const_syntax csplit},_) $ t) = |
147 | dest_LAM (Const (@{const_syntax Rep_cfun},_) $ Const (@{const_syntax csplit},_) $ t) = |
148 let |
148 let |
163 Syntax.const @{syntax_const "_Case1"} $ |
163 Syntax.const @{syntax_const "_Case1"} $ |
164 (Syntax.const @{syntax_const "_match"} $ p $ v) $ t |
164 (Syntax.const @{syntax_const "_match"} $ p $ v) $ t |
165 end; |
165 end; |
166 |
166 |
167 in [(@{const_syntax Rep_cfun}, K Case1_tr')] end; |
167 in [(@{const_syntax Rep_cfun}, K Case1_tr')] end; |
168 *} |
168 \<close> |
169 |
169 |
170 translations |
170 translations |
171 "x" <= "_match (CONST succeed) (_variable x)" |
171 "x" <= "_match (CONST succeed) (_variable x)" |
172 |
172 |
173 |
173 |
174 subsection {* Pattern combinators for data constructors *} |
174 subsection \<open>Pattern combinators for data constructors\<close> |
175 |
175 |
176 type_synonym ('a, 'b) pat = "'a \<rightarrow> 'b match" |
176 type_synonym ('a, 'b) pat = "'a \<rightarrow> 'b match" |
177 |
177 |
178 definition |
178 definition |
179 cpair_pat :: "('a, 'c) pat \<Rightarrow> ('b, 'd) pat \<Rightarrow> ('a \<times> 'b, 'c \<times> 'd) pat" where |
179 cpair_pat :: "('a, 'c) pat \<Rightarrow> ('b, 'd) pat \<Rightarrow> ('a \<times> 'b, 'c \<times> 'd) pat" where |
207 |
207 |
208 definition |
208 definition |
209 ONE_pat :: "(one, unit) pat" where |
209 ONE_pat :: "(one, unit) pat" where |
210 "ONE_pat = (\<Lambda> ONE. succeed\<cdot>())" |
210 "ONE_pat = (\<Lambda> ONE. succeed\<cdot>())" |
211 |
211 |
212 text {* Parse translations (patterns) *} |
212 text \<open>Parse translations (patterns)\<close> |
213 translations |
213 translations |
214 "_pat (XCONST Pair x y)" => "CONST cpair_pat (_pat x) (_pat y)" |
214 "_pat (XCONST Pair x y)" => "CONST cpair_pat (_pat x) (_pat y)" |
215 "_pat (XCONST spair\<cdot>x\<cdot>y)" => "CONST spair_pat (_pat x) (_pat y)" |
215 "_pat (XCONST spair\<cdot>x\<cdot>y)" => "CONST spair_pat (_pat x) (_pat y)" |
216 "_pat (XCONST sinl\<cdot>x)" => "CONST sinl_pat (_pat x)" |
216 "_pat (XCONST sinl\<cdot>x)" => "CONST sinl_pat (_pat x)" |
217 "_pat (XCONST sinr\<cdot>x)" => "CONST sinr_pat (_pat x)" |
217 "_pat (XCONST sinr\<cdot>x)" => "CONST sinr_pat (_pat x)" |
218 "_pat (XCONST up\<cdot>x)" => "CONST up_pat (_pat x)" |
218 "_pat (XCONST up\<cdot>x)" => "CONST up_pat (_pat x)" |
219 "_pat (XCONST TT)" => "CONST TT_pat" |
219 "_pat (XCONST TT)" => "CONST TT_pat" |
220 "_pat (XCONST FF)" => "CONST FF_pat" |
220 "_pat (XCONST FF)" => "CONST FF_pat" |
221 "_pat (XCONST ONE)" => "CONST ONE_pat" |
221 "_pat (XCONST ONE)" => "CONST ONE_pat" |
222 |
222 |
223 text {* CONST version is also needed for constructors with special syntax *} |
223 text \<open>CONST version is also needed for constructors with special syntax\<close> |
224 translations |
224 translations |
225 "_pat (CONST Pair x y)" => "CONST cpair_pat (_pat x) (_pat y)" |
225 "_pat (CONST Pair x y)" => "CONST cpair_pat (_pat x) (_pat y)" |
226 "_pat (CONST spair\<cdot>x\<cdot>y)" => "CONST spair_pat (_pat x) (_pat y)" |
226 "_pat (CONST spair\<cdot>x\<cdot>y)" => "CONST spair_pat (_pat x) (_pat y)" |
227 |
227 |
228 text {* Parse translations (variables) *} |
228 text \<open>Parse translations (variables)\<close> |
229 translations |
229 translations |
230 "_variable (XCONST Pair x y) r" => "_variable (_args x y) r" |
230 "_variable (XCONST Pair x y) r" => "_variable (_args x y) r" |
231 "_variable (XCONST spair\<cdot>x\<cdot>y) r" => "_variable (_args x y) r" |
231 "_variable (XCONST spair\<cdot>x\<cdot>y) r" => "_variable (_args x y) r" |
232 "_variable (XCONST sinl\<cdot>x) r" => "_variable x r" |
232 "_variable (XCONST sinl\<cdot>x) r" => "_variable x r" |
233 "_variable (XCONST sinr\<cdot>x) r" => "_variable x r" |
233 "_variable (XCONST sinr\<cdot>x) r" => "_variable x r" |
238 |
238 |
239 translations |
239 translations |
240 "_variable (CONST Pair x y) r" => "_variable (_args x y) r" |
240 "_variable (CONST Pair x y) r" => "_variable (_args x y) r" |
241 "_variable (CONST spair\<cdot>x\<cdot>y) r" => "_variable (_args x y) r" |
241 "_variable (CONST spair\<cdot>x\<cdot>y) r" => "_variable (_args x y) r" |
242 |
242 |
243 text {* Print translations *} |
243 text \<open>Print translations\<close> |
244 translations |
244 translations |
245 "CONST Pair (_match p1 v1) (_match p2 v2)" |
245 "CONST Pair (_match p1 v1) (_match p2 v2)" |
246 <= "_match (CONST cpair_pat p1 p2) (_args v1 v2)" |
246 <= "_match (CONST cpair_pat p1 p2) (_args v1 v2)" |
247 "CONST spair\<cdot>(_match p1 v1)\<cdot>(_match p2 v2)" |
247 "CONST spair\<cdot>(_match p1 v1)\<cdot>(_match p2 v2)" |
248 <= "_match (CONST spair_pat p1 p2) (_args v1 v2)" |
248 <= "_match (CONST spair_pat p1 p2) (_args v1 v2)" |
316 "branch ONE_pat\<cdot>(unit_when\<cdot>r)\<cdot>\<bottom> = \<bottom>" |
316 "branch ONE_pat\<cdot>(unit_when\<cdot>r)\<cdot>\<bottom> = \<bottom>" |
317 "branch ONE_pat\<cdot>(unit_when\<cdot>r)\<cdot>ONE = succeed\<cdot>r" |
317 "branch ONE_pat\<cdot>(unit_when\<cdot>r)\<cdot>ONE = succeed\<cdot>r" |
318 by (simp_all add: branch_def ONE_pat_def) |
318 by (simp_all add: branch_def ONE_pat_def) |
319 |
319 |
320 |
320 |
321 subsection {* Wildcards, as-patterns, and lazy patterns *} |
321 subsection \<open>Wildcards, as-patterns, and lazy patterns\<close> |
322 |
322 |
323 definition |
323 definition |
324 wild_pat :: "'a \<rightarrow> unit match" where |
324 wild_pat :: "'a \<rightarrow> unit match" where |
325 "wild_pat = (\<Lambda> x. succeed\<cdot>())" |
325 "wild_pat = (\<Lambda> x. succeed\<cdot>())" |
326 |
326 |
330 |
330 |
331 definition |
331 definition |
332 lazy_pat :: "('a \<rightarrow> 'b::pcpo match) \<Rightarrow> ('a \<rightarrow> 'b match)" where |
332 lazy_pat :: "('a \<rightarrow> 'b::pcpo match) \<Rightarrow> ('a \<rightarrow> 'b match)" where |
333 "lazy_pat p = (\<Lambda> x. succeed\<cdot>(cases\<cdot>(p\<cdot>x)))" |
333 "lazy_pat p = (\<Lambda> x. succeed\<cdot>(cases\<cdot>(p\<cdot>x)))" |
334 |
334 |
335 text {* Parse translations (patterns) *} |
335 text \<open>Parse translations (patterns)\<close> |
336 translations |
336 translations |
337 "_pat _" => "CONST wild_pat" |
337 "_pat _" => "CONST wild_pat" |
338 |
338 |
339 text {* Parse translations (variables) *} |
339 text \<open>Parse translations (variables)\<close> |
340 translations |
340 translations |
341 "_variable _ r" => "_variable _noargs r" |
341 "_variable _ r" => "_variable _noargs r" |
342 |
342 |
343 text {* Print translations *} |
343 text \<open>Print translations\<close> |
344 translations |
344 translations |
345 "_" <= "_match (CONST wild_pat) _noargs" |
345 "_" <= "_match (CONST wild_pat) _noargs" |
346 |
346 |
347 lemma wild_pat [simp]: "branch wild_pat\<cdot>(unit_when\<cdot>r)\<cdot>x = succeed\<cdot>r" |
347 lemma wild_pat [simp]: "branch wild_pat\<cdot>(unit_when\<cdot>r)\<cdot>x = succeed\<cdot>r" |
348 by (simp add: branch_def wild_pat_def) |
348 by (simp add: branch_def wild_pat_def) |
359 "branch p\<cdot>r\<cdot>x = succeed\<cdot>s \<Longrightarrow> branch (lazy_pat p)\<cdot>r\<cdot>x = succeed\<cdot>s" |
359 "branch p\<cdot>r\<cdot>x = succeed\<cdot>s \<Longrightarrow> branch (lazy_pat p)\<cdot>r\<cdot>x = succeed\<cdot>s" |
360 apply (simp_all add: branch_def lazy_pat_def) |
360 apply (simp_all add: branch_def lazy_pat_def) |
361 apply (cases "p\<cdot>x", simp_all)+ |
361 apply (cases "p\<cdot>x", simp_all)+ |
362 done |
362 done |
363 |
363 |
364 subsection {* Examples *} |
364 subsection \<open>Examples\<close> |
365 |
365 |
366 term "Case t of (:up\<cdot>(sinl\<cdot>x), sinr\<cdot>y:) \<Rightarrow> (x, y)" |
366 term "Case t of (:up\<cdot>(sinl\<cdot>x), sinr\<cdot>y:) \<Rightarrow> (x, y)" |
367 |
367 |
368 term "\<Lambda> t. Case t of up\<cdot>(sinl\<cdot>a) \<Rightarrow> a | up\<cdot>(sinr\<cdot>b) \<Rightarrow> b" |
368 term "\<Lambda> t. Case t of up\<cdot>(sinl\<cdot>a) \<Rightarrow> a | up\<cdot>(sinr\<cdot>b) \<Rightarrow> b" |
369 |
369 |
370 term "\<Lambda> t. Case t of (:up\<cdot>(sinl\<cdot>_), sinr\<cdot>x:) \<Rightarrow> x" |
370 term "\<Lambda> t. Case t of (:up\<cdot>(sinl\<cdot>_), sinr\<cdot>x:) \<Rightarrow> x" |
371 |
371 |
372 subsection {* ML code for generating definitions *} |
372 subsection \<open>ML code for generating definitions\<close> |
373 |
373 |
374 ML {* |
374 ML \<open> |
375 local open HOLCF_Library in |
375 local open HOLCF_Library in |
376 |
376 |
377 infixr 6 ->>; |
377 infixr 6 ->>; |
378 infix 9 ` ; |
378 infix 9 ` ; |
379 |
379 |