|
66451
|
1 |
(* Title: HOL/Library/Pattern_Aliases.thy
|
|
|
2 |
Author: Lars Hupel, Ondrej Kuncar
|
|
|
3 |
*)
|
|
|
4 |
|
|
|
5 |
section \<open>Input syntax for pattern aliases (or ``as-patterns'' in Haskell)\<close>
|
|
|
6 |
|
|
|
7 |
theory Pattern_Aliases
|
|
|
8 |
imports Main
|
|
|
9 |
begin
|
|
|
10 |
|
|
|
11 |
text \<open>
|
|
|
12 |
Most functional languages (Haskell, ML, Scala) support aliases in patterns. This allows to refer
|
|
|
13 |
to a subpattern with a variable name. This theory implements this using a check phase. It works
|
|
|
14 |
well for function definitions (see usage below).
|
|
|
15 |
|
|
|
16 |
The following caveats should be kept in mind:
|
|
|
17 |
\<^item> The translation expects a term of the form @{prop "f x y = rhs"}, where \<open>x\<close> and \<open>y\<close> are patterns
|
|
|
18 |
that may contain aliases. The result of the translation is a nested @{const Let}-expression on
|
|
|
19 |
the right hand side. The code generator \<^emph>\<open>does not\<close> print Isabelle pattern aliases to target
|
|
|
20 |
language pattern aliases.
|
|
|
21 |
\<^item> The translation does not process nested equalities; only the top-level equality is translated.
|
|
|
22 |
\<^item> Terms that do not adhere to the above shape may either stay untranslated or produce an error
|
|
|
23 |
message. The @{command fun} command will complain if pattern aliases are left untranslated.
|
|
|
24 |
In particular, there are no checks whether the patterns are wellformed or linear.
|
|
|
25 |
\<^item> There is no corresonding uncheck phase, because it is unclear in which situations the
|
|
|
26 |
translation should be reversed.
|
|
|
27 |
\<close>
|
|
|
28 |
|
|
|
29 |
|
|
|
30 |
subsection \<open>Definition\<close>
|
|
|
31 |
|
|
|
32 |
consts as :: "'a \<Rightarrow> 'a \<Rightarrow> 'a"
|
|
|
33 |
|
|
|
34 |
ML\<open>
|
|
|
35 |
local
|
|
|
36 |
|
|
|
37 |
fun let_typ a b = a --> (a --> b) --> b
|
|
|
38 |
|
|
|
39 |
fun strip_all t =
|
|
|
40 |
case try Logic.dest_all t of
|
|
|
41 |
NONE => ([], t)
|
|
|
42 |
| SOME (var, t) => apfst (cons var) (strip_all t)
|
|
|
43 |
|
|
|
44 |
fun all_Frees t =
|
|
|
45 |
fold_aterms (fn Free (x, t) => insert op = (x, t) | _ => I) t []
|
|
|
46 |
|
|
|
47 |
in
|
|
|
48 |
|
|
|
49 |
fun check_pattern_syntax t =
|
|
|
50 |
case strip_all t of
|
|
|
51 |
(vars, @{const Trueprop} $ (Const (@{const_name HOL.eq}, _) $ lhs $ rhs)) =>
|
|
|
52 |
let
|
|
|
53 |
fun go (Const (@{const_name as}, _) $ pat $ var, rhs) =
|
|
|
54 |
let
|
|
|
55 |
val (pat', rhs') = go (pat, rhs)
|
|
|
56 |
val _ = if is_Free var then () else error "Left-hand side of =: must be a free variable"
|
|
|
57 |
val rhs'' =
|
|
|
58 |
Const (@{const_name Let}, let_typ (fastype_of var) (fastype_of rhs)) $
|
|
|
59 |
pat' $ lambda var rhs'
|
|
|
60 |
in
|
|
|
61 |
(pat', rhs'')
|
|
|
62 |
end
|
|
|
63 |
| go (t $ u, rhs) =
|
|
|
64 |
let
|
|
|
65 |
val (t', rhs') = go (t, rhs)
|
|
|
66 |
val (u', rhs'') = go (u, rhs')
|
|
|
67 |
in (t' $ u', rhs'') end
|
|
|
68 |
| go (t, rhs) = (t, rhs)
|
|
|
69 |
|
|
|
70 |
val (lhs', rhs') = go (lhs, rhs)
|
|
|
71 |
|
|
|
72 |
val res = HOLogic.mk_Trueprop (HOLogic.mk_eq (lhs', rhs'))
|
|
|
73 |
|
|
|
74 |
val frees = filter (member op = vars) (all_Frees res)
|
|
|
75 |
in fold (fn v => Logic.dependent_all_name ("", v)) (map Free frees) res end
|
|
|
76 |
| _ => t
|
|
|
77 |
|
|
|
78 |
end
|
|
|
79 |
\<close>
|
|
|
80 |
|
|
|
81 |
bundle pattern_aliases begin
|
|
|
82 |
|
|
|
83 |
notation as (infixr "=:" 1)
|
|
|
84 |
|
|
|
85 |
declaration \<open>K (Syntax_Phases.term_check 98 "pattern_syntax" (K (map check_pattern_syntax)))\<close>
|
|
|
86 |
|
|
|
87 |
end
|
|
|
88 |
|
|
|
89 |
hide_const (open) as
|
|
|
90 |
|
|
|
91 |
|
|
|
92 |
subsection \<open>Usage\<close>
|
|
|
93 |
|
|
|
94 |
context includes pattern_aliases begin
|
|
|
95 |
|
|
|
96 |
text \<open>Not very useful for plain definitions, but works anyway.\<close>
|
|
|
97 |
|
|
|
98 |
private definition "test_1 x (y =: z) = y + z"
|
|
|
99 |
|
|
|
100 |
lemma "test_1 x y = y + y"
|
|
|
101 |
by (rule test_1_def[unfolded Let_def])
|
|
|
102 |
|
|
|
103 |
text \<open>Very useful for function definitions.\<close>
|
|
|
104 |
|
|
|
105 |
private fun test_2 where
|
|
|
106 |
"test_2 (y # (y' # ys =: x') =: x) = x @ x'" |
|
|
|
107 |
"test_2 _ = []"
|
|
|
108 |
|
|
|
109 |
lemma "test_2 (y # y' # ys) = (y # y' # ys) @ y' # ys"
|
|
|
110 |
by (rule test_2.simps[unfolded Let_def])
|
|
|
111 |
|
|
|
112 |
end
|
|
|
113 |
|
|
|
114 |
end |