1 (* Title: HOL/ex/Points.thy |
1 (* Title: HOL/ex/Points.thy |
2 ID: $Id$ |
2 ID: $Id$ |
3 Author: Wolfgang Naraschewski and Markus Wenzel, TU Muenchen |
3 Author: Wolfgang Naraschewski and Markus Wenzel, TU Muenchen |
4 *) |
4 *) |
5 |
5 |
6 theory Points = Main:; |
6 theory Points = Main: |
7 |
7 |
8 text {* Basic use of extensible records in HOL, including the famous points |
8 text {* Basic use of extensible records in HOL, including the famous points |
9 and coloured points. *}; |
9 and coloured points. *} |
10 |
10 |
11 |
11 |
12 section {* Points *}; |
12 section {* Points *} |
13 |
13 |
14 record point = |
14 record point = |
15 x :: nat |
15 x :: nat |
16 y :: nat; |
16 y :: nat |
17 |
17 |
18 text {* |
18 text {* |
19 Apart many other things, above record declaration produces the |
19 Apart many other things, above record declaration produces the |
20 following theorems: |
20 following theorems: |
|
21 *} |
21 |
22 |
22 thms "point.simps" |
23 thm "point.simps" |
23 thms "point.iffs" |
24 thm "point.iffs" |
24 thms "point.update_defs" |
25 thm "point.update_defs" |
25 |
26 |
26 The set of theorems "point.simps" is added automatically to the |
27 text {* |
27 standard simpset, "point.iffs" is added to the claset and simpset. |
28 The set of theorems "point.simps" is added automatically to the |
28 *}; |
29 standard simpset, "point.iffs" is added to the claset and simpset. |
|
30 *} |
29 |
31 |
30 text {* |
32 text {* |
31 Record declarations define new type abbreviations: |
33 Record declarations define new type abbreviations: |
32 |
34 |
33 point = "(| x :: nat, y :: nat |)" |
35 point = "(| x :: nat, y :: nat |)" |
34 'a point_scheme = "(| x :: nat, y :: nat, ... :: 'a |)" |
36 'a point_scheme = "(| x :: nat, y :: nat, ... :: 'a |)" |
35 |
37 |
36 Extensions `...' must be in type class `more'! |
38 Extensions `...' must be in type class `more'! |
37 *}; |
39 *} |
38 |
40 |
39 consts foo1 :: point; |
41 consts foo1 :: point |
40 consts foo2 :: "(| x :: nat, y :: nat |)"; |
42 consts foo2 :: "(| x :: nat, y :: nat |)" |
41 consts foo3 :: "'a => ('a::more) point_scheme"; |
43 consts foo3 :: "'a => ('a::more) point_scheme" |
42 consts foo4 :: "'a => (| x :: nat, y :: nat, ... :: 'a |)"; |
44 consts foo4 :: "'a => (| x :: nat, y :: nat, ... :: 'a |)" |
43 |
45 |
44 |
46 |
45 subsection {* Introducing concrete records and record schemes *}; |
47 subsection {* Introducing concrete records and record schemes *} |
46 |
48 |
47 defs |
49 defs |
48 foo1_def: "foo1 == (| x = 1, y = 0 |)" |
50 foo1_def: "foo1 == (| x = 1, y = 0 |)" |
49 foo3_def: "foo3 ext == (| x = 1, y = 0, ... = ext |)"; |
51 foo3_def: "foo3 ext == (| x = 1, y = 0, ... = ext |)" |
50 |
52 |
51 |
53 |
52 subsection {* Record selection and record update *}; |
54 subsection {* Record selection and record update *} |
53 |
55 |
54 constdefs |
56 constdefs |
55 getX :: "('a::more) point_scheme => nat" |
57 getX :: "('a::more) point_scheme => nat" |
56 "getX r == x r" |
58 "getX r == x r" |
57 setX :: "('a::more) point_scheme => nat => 'a point_scheme" |
59 setX :: "('a::more) point_scheme => nat => 'a point_scheme" |
58 "setX r n == r (| x := n |)"; |
60 "setX r n == r (| x := n |)" |
59 |
61 |
60 |
62 |
61 subsection {* Some lemmas about records *}; |
63 subsection {* Some lemmas about records *} |
62 |
64 |
63 text {* Note: any of these goals may be solved with a single |
65 text {* basic simplifications *} |
64 stroke of the auto or force proof method. *}; |
66 |
|
67 lemma "x (| x = m, y = n, ... = p |) = m" |
|
68 by simp |
|
69 |
|
70 lemma "(| x = m, y = n, ... = p |) (| x:= 0 |) = (| x = 0, y = n, ... = p |)" |
|
71 by simp |
65 |
72 |
66 |
73 |
67 text {* basic simplifications *}; |
74 text {* splitting quantifiers: the !!r is NECESSARY here *} |
68 |
75 |
69 lemma "x (| x = m, y = n, ... = p |) = m"; |
76 lemma "!!r. r (| x := n |) (| y := m |) = r (| y := m |) (| x := n |)" |
70 by simp; |
77 proof record_split |
|
78 fix x y more |
|
79 show "(| x = x, y = y, ... = more |)(| x := n, y := m |) = |
|
80 (| x = x, y = y, ... = more |)(| y := m, x := n |)" |
|
81 by simp |
|
82 qed |
71 |
83 |
72 lemma "(| x = m, y = n, ... = p |) (| x:= 0 |) = (| x = 0, y = n, ... = p |)"; |
84 lemma "!!r. r (| x := n |) (| x := m |) = r (| x := m |)" |
73 by simp; |
85 proof record_split |
|
86 fix x y more |
|
87 show "(| x = x, y = y, ... = more |)(| x := n, x := m |) = |
|
88 (| x = x, y = y, ... = more |)(| x := m |)" |
|
89 by simp |
|
90 qed |
74 |
91 |
75 |
92 |
76 text {* splitting quantifiers: the !!r is NECESSARY *}; |
93 text {* equality of records *} |
77 |
94 |
78 lemma "!!r. r (| x := n |) (| y := m |) = r (| y := m |) (| x := n |)"; |
95 lemma "(| x = n, y = p |) = (| x = n', y = p' |) ==> n = n'" |
79 proof record_split; |
96 by simp |
80 fix a b rest; |
|
81 show "(| x = a, y = b, ... = rest |)(| x := n, y := m |) = |
|
82 (| x = a, y = b, ... = rest |)(| y := m, x := n |)"; |
|
83 by simp; |
|
84 qed; |
|
85 |
|
86 lemma "!!r. r (| x := n |) (| x := m |) = r (| x := m |)"; |
|
87 proof record_split; |
|
88 fix a b rest; |
|
89 show "(| x = a, y = b, ... = rest |)(| x := n, x := m |) = |
|
90 (| x = a, y = b, ... = rest |)(| x := m |)"; |
|
91 by simp; |
|
92 qed; |
|
93 |
97 |
94 |
98 |
95 text {* equality of records *}; |
99 text {* concrete records are type instances of record schemes *} |
96 |
|
97 lemma "(| x = n, y = p |) = (| x = n', y = p' |) --> n = n'" (is "?EQ --> _"); |
|
98 proof; |
|
99 assume ?EQ; |
|
100 thus "n = n'"; by simp; |
|
101 qed; |
|
102 |
|
103 |
|
104 text {* concrete records are type instances of record schemes *}; |
|
105 |
100 |
106 constdefs |
101 constdefs |
107 foo5 :: nat |
102 foo5 :: nat |
108 "foo5 == getX (| x = 1, y = 0 |)"; |
103 "foo5 == getX (| x = 1, y = 0 |)" |
109 |
104 |
110 |
105 |
111 text {* manipulating the `...' (more) part *}; |
106 text {* manipulating the `...' (more) part *} |
112 |
107 |
113 constdefs |
108 constdefs |
114 incX :: "('a::more) point_scheme => 'a point_scheme" |
109 incX :: "('a::more) point_scheme => 'a point_scheme" |
115 "incX r == (| x = Suc (x r), y = y r, ... = point.more r |)"; |
110 "incX r == (| x = Suc (x r), y = y r, ... = point.more r |)" |
116 |
111 |
117 lemma "!!r n. incX r = setX r (Suc (getX r))"; |
112 lemma "!!r n. incX r = setX r (Suc (getX r))" |
118 proof (unfold getX_def setX_def incX_def); |
113 proof (unfold getX_def setX_def incX_def) |
119 show "!! r n. (| x = Suc (x r), y = y r, ... = more r |) = r(| x := Suc (x r) |)"; |
114 show "!! r n. (| x = Suc (x r), y = y r, ... = more r |) = r(| x := Suc (x r) |)" |
120 by (record_split, simp); |
115 by record_split simp |
121 qed; |
116 qed |
122 |
117 |
123 |
118 |
124 text {* alternative definition *}; |
119 text {* alternative definition *} |
125 |
120 |
126 constdefs |
121 constdefs |
127 incX' :: "('a::more) point_scheme => 'a point_scheme" |
122 incX' :: "('a::more) point_scheme => 'a point_scheme" |
128 "incX' r == r (| x := Suc (x r) |)"; |
123 "incX' r == r (| x := Suc (x r) |)" |
129 |
124 |
130 |
125 |
131 |
126 |
132 section {* coloured points: record extension *}; |
127 section {* coloured points: record extension *} |
133 |
128 |
134 datatype colour = Red | Green | Blue; |
129 datatype colour = Red | Green | Blue |
135 |
130 |
136 record cpoint = point + |
131 record cpoint = point + |
137 colour :: colour; |
132 colour :: colour |
138 |
133 |
139 |
134 |
140 text {* |
135 text {* |
141 The record declaration defines new type constructors: |
136 The record declaration defines new type constructors: |
142 |
137 |
143 cpoint = (| x :: nat, y :: nat, colour :: colour |) |
138 cpoint = (| x :: nat, y :: nat, colour :: colour |) |
144 'a cpoint_scheme = (| x :: nat, y :: nat, colour :: colour, ... :: 'a |) |
139 'a cpoint_scheme = (| x :: nat, y :: nat, colour :: colour, ... :: 'a |) |
145 *}; |
140 *} |
146 |
141 |
147 consts foo6 :: cpoint; |
142 consts foo6 :: cpoint |
148 consts foo7 :: "(| x :: nat, y :: nat, colour :: colour |)"; |
143 consts foo7 :: "(| x :: nat, y :: nat, colour :: colour |)" |
149 consts foo8 :: "('a::more) cpoint_scheme"; |
144 consts foo8 :: "('a::more) cpoint_scheme" |
150 consts foo9 :: "(| x :: nat, y :: nat, colour :: colour, ... :: 'a |)"; |
145 consts foo9 :: "(| x :: nat, y :: nat, colour :: colour, ... :: 'a |)" |
151 |
146 |
152 |
147 |
153 text {* functions on point schemes work for cpoints as well *}; |
148 text {* functions on point schemes work for cpoints as well *} |
154 |
149 |
155 constdefs |
150 constdefs |
156 foo10 :: nat |
151 foo10 :: nat |
157 "foo10 == getX (| x = 2, y = 0, colour = Blue |)"; |
152 "foo10 == getX (| x = 2, y = 0, colour = Blue |)" |
158 |
153 |
159 |
154 |
160 subsection {* Non-coercive structural subtyping *}; |
155 subsection {* Non-coercive structural subtyping *} |
161 |
156 |
162 text {* foo11 has type cpoint, not type point --- Great! *}; |
157 text {* foo11 has type cpoint, not type point --- Great! *} |
163 |
158 |
164 constdefs |
159 constdefs |
165 foo11 :: cpoint |
160 foo11 :: cpoint |
166 "foo11 == setX (| x = 2, y = 0, colour = Blue |) 0"; |
161 "foo11 == setX (| x = 2, y = 0, colour = Blue |) 0" |
167 |
162 |
168 |
163 |
169 |
164 |
170 section {* Other features *}; |
165 section {* Other features *} |
171 |
166 |
172 text {* field names contribute to record identity *}; |
167 text {* field names contribute to record identity *} |
173 |
168 |
174 record point' = |
169 record point' = |
175 x' :: nat |
170 x' :: nat |
176 y' :: nat; |
171 y' :: nat |
177 |
172 |
178 consts |
173 consts |
179 foo12 :: nat; |
174 foo12 :: nat |
180 |
175 |
181 text {* Definition @{term "foo12 == getX (| x' = 2, y' = 0 |)"} is invalid *}; |
176 text {* Definition @{term "foo12 == getX (| x' = 2, y' = 0 |)"} is invalid *} |
182 |
177 |
183 |
178 |
184 text {* polymorphic records *}; |
179 text {* polymorphic records *} |
185 |
180 |
186 record 'a point'' = point + |
181 record 'a point'' = point + |
187 content :: 'a; |
182 content :: 'a |
188 |
183 |
189 types cpoint'' = "colour point''"; |
184 types cpoint'' = "colour point''" |
190 |
185 |
191 |
186 end |
192 text {* Have a lot of fun! *}; |
|
193 |
|
194 end; |
|