226 subsubsection {* List comprehehsion *} |
226 subsubsection {* List comprehehsion *} |
227 |
227 |
228 text{* Input syntax for Haskell-like list comprehension |
228 text{* Input syntax for Haskell-like list comprehension |
229 notation. Typical example: @{text"[(x,y). x \<leftarrow> xs, y \<leftarrow> ys, x \<noteq> y]"}, the list of all pairs of distinct elements from @{text xs} and @{text ys}. |
229 notation. Typical example: @{text"[(x,y). x \<leftarrow> xs, y \<leftarrow> ys, x \<noteq> y]"}, the list of all pairs of distinct elements from @{text xs} and @{text ys}. |
230 |
230 |
231 There are a number of differences to Haskell. The general synatx is |
231 There are two differences to Haskell. The general synatx is |
232 @{text"[e. p \<leftarrow> xs, \<dots>]"} rather than \verb![x| x <- xs, ...]!. The |
232 @{text"[e. p \<leftarrow> xs, \<dots>]"} rather than \verb![x| x <- xs, ...]!. Patterns in |
233 first qualifier must be a generator (@{text"p \<leftarrow> xs"}). Patterns in |
233 generators can only be tuples (at the moment). |
234 generators can only be tuples (at the moment). Finally, guards are |
234 |
235 translated into filters, which simplifies theorem proving. |
235 To avoid misunderstandings, the translation is not reversed upon |
|
236 output. You can add the inverse translations in your own theory if you |
|
237 desire. |
|
238 |
|
239 Hint: formulae containing complex list comprehensions may become quite |
|
240 unreadable after the simplifier has finished with them. It can be |
|
241 helpful to introduce definitions for such list comprehensions and |
|
242 treat them separately in suitable lemmas. |
236 *} |
243 *} |
237 (* |
244 (* |
238 The print translation from internal form to list comprehensions would |
245 Proper theorem proving support would be nice. For example, if |
239 be nice. Unfortunately one cannot just turn the translations around |
|
240 because in the final equality @{text p} occurs twice on the |
|
241 right-hand side. Due to this restriction, the translation must be hand-coded. |
|
242 |
|
243 A more substantial extension would be proper theorem proving |
|
244 support. For example, it would be nice if |
|
245 @{text"set[f x y. x \<leftarrow> xs, y \<leftarrow> ys, P x y]"} |
246 @{text"set[f x y. x \<leftarrow> xs, y \<leftarrow> ys, P x y]"} |
246 produced something like |
247 produced something like |
247 @{term"{z. EX x: set xs. EX y:set ys. P x y \<and> z = f x y}"}. |
248 @{term"{z. EX x: set xs. EX y:set ys. P x y \<and> z = f x y}"}. |
248 *) |
249 *) |
249 |
250 |
250 nonterminals lc_qual |
251 nonterminals lc_qual lc_quals |
251 |
252 |
252 syntax |
253 syntax |
253 "_listcompr" :: "'a \<Rightarrow> pttrn \<Rightarrow> 'b list \<Rightarrow> lc_qual \<Rightarrow> 'a list" ("[_ . _ \<leftarrow> __") |
254 "_listcompr" :: "'a \<Rightarrow> lc_qual \<Rightarrow> lc_quals \<Rightarrow> 'a list" ("[_ . __") |
254 "_listcompr" :: "'a \<Rightarrow> pttrn \<Rightarrow> 'b list \<Rightarrow> lc_qual \<Rightarrow> 'a list" ("[_ . _ <- __") |
255 "_lc_gen" :: "pttrn \<Rightarrow> 'a list \<Rightarrow> lc_qual" ("_ \<leftarrow> _") |
255 "_lc_end" :: "lc_qual" ("]") |
256 "_lc_gen" :: "pttrn \<Rightarrow> 'a list \<Rightarrow> lc_qual" ("_ <- _") |
256 "_lc_gen" :: "pttrn \<Rightarrow> 'a list \<Rightarrow> lc_qual \<Rightarrow> lc_qual" (",_ \<leftarrow> __") |
257 "_lc_test" :: "bool \<Rightarrow> lc_qual" ("_") |
257 "_lc_gen" :: "pttrn \<Rightarrow> 'a list \<Rightarrow> lc_qual \<Rightarrow> lc_qual" (",_ <- __") |
258 "_lc_end" :: "lc_quals" ("]") |
258 "_lc_test" :: "bool \<Rightarrow> lc_qual \<Rightarrow> lc_qual" (",__") |
259 "_lc_quals" :: "lc_qual \<Rightarrow> lc_quals \<Rightarrow> lc_quals" (", __") |
259 |
|
260 |
260 |
261 translations |
261 translations |
262 "[e. p\<leftarrow>xs]" => "map (%p. e) xs" |
262 "[e. p\<leftarrow>xs]" => "map (%p. e) xs" |
263 "_listcompr e p xs (_lc_gen q ys Q)" => |
263 "_listcompr e (_lc_gen p xs) (_lc_quals Q Qs)" |
264 "concat (map (%p. _listcompr e q ys Q) xs)" |
264 => "concat (map (%p. _listcompr e Q Qs) xs)" |
265 "_listcompr e p xs (_lc_test P Q)" => "_listcompr e p (filter (%p. P) xs) Q" |
265 "[e. P]" => "if P then [e] else []" |
266 |
266 "_listcompr e (_lc_test P) (_lc_quals Q Qs)" |
267 (* Some examples: |
267 => "if P then (_listcompr e Q Qs) else []" |
268 term "[(x,y). x \<leftarrow> xs, x<y]" |
268 |
269 term "[(x,y). x \<leftarrow> xs, x<y, z\<leftarrow>zs]" |
269 (* |
270 term "[(x,y). x \<leftarrow> xs, y \<leftarrow> ys, x<y]" |
270 term "[(x,y,z). b]" |
271 term "[(x,y,z). x \<leftarrow> xs, y \<leftarrow> ys, z\<leftarrow> zs]" |
271 term "[(x,y,z). x \<leftarrow> xs]" |
272 term "[x. x \<leftarrow> xs, x < a, x > b]" |
272 term "[(x,y,z). x<a, x>b]" |
|
273 term "[(x,y,z). x<a, x\<leftarrow>xs]" |
|
274 term "[(x,y,z). x\<leftarrow>xs, x>b]" |
|
275 term "[(x,y,z). x\<leftarrow>xs, y\<leftarrow>ys]" |
|
276 term "[(x,y,z). x<a, x>b, x=d]" |
|
277 term "[(x,y,z). x<a, x>b, y\<leftarrow>ys]" |
|
278 term "[(x,y,z). x<a, x\<leftarrow>xs,y>b]" |
|
279 term "[(x,y,z). x<a, x\<leftarrow>xs, y\<leftarrow>ys]" |
|
280 term "[(x,y,z). x\<leftarrow>xs, x>b, y<a]" |
|
281 term "[(x,y,z). x\<leftarrow>xs, x>b, y\<leftarrow>ys]" |
|
282 term "[(x,y,z). x\<leftarrow>xs, y\<leftarrow>ys,y>x]" |
|
283 term "[(x,y,z). x\<leftarrow>xs, y\<leftarrow>ys,z\<leftarrow>zs]" |
273 *) |
284 *) |
|
285 |
274 |
286 |
275 subsubsection {* @{const Nil} and @{const Cons} *} |
287 subsubsection {* @{const Nil} and @{const Cons} *} |
276 |
288 |
277 lemma not_Cons_self [simp]: |
289 lemma not_Cons_self [simp]: |
278 "xs \<noteq> x # xs" |
290 "xs \<noteq> x # xs" |