author | kleing |
Tue, 13 Apr 2004 10:45:35 +0200 | |
changeset 14552 | e88f52b775a5 |
parent 14379 | ea10a8c3e9cf |
child 15481 | fc075ae929e4 |
permissions | -rw-r--r-- |
12572 | 1 |
% |
2 |
\begin{isabellebody}% |
|
3 |
\def\isabellecontext{Records}% |
|
4 |
% |
|
5 |
\isamarkupheader{Records \label{sec:records}% |
|
6 |
} |
|
7 |
\isamarkuptrue% |
|
8 |
\isamarkupfalse% |
|
9 |
% |
|
10 |
\begin{isamarkuptext}% |
|
11 |
\index{records|(}% |
|
12 |
Records are familiar from programming languages. A record of $n$ |
|
13 |
fields is essentially an $n$-tuple, but the record's components have |
|
14 |
names, which can make expressions easier to read and reduces the |
|
15 |
risk of confusing one field for another. |
|
16 |
||
12585 | 17 |
A record of Isabelle/HOL covers a collection of fields, with select |
12572 | 18 |
and update operations. Each field has a specified type, which may |
19 |
be polymorphic. The field names are part of the record type, and |
|
20 |
the order of the fields is significant --- as it is in Pascal but |
|
21 |
not in Standard ML. If two different record types have field names |
|
22 |
in common, then the ambiguity is resolved in the usual way, by |
|
23 |
qualified names. |
|
24 |
||
25 |
Record types can also be defined by extending other record types. |
|
26 |
Extensible records make use of the reserved pseudo-field \cdx{more}, |
|
27 |
which is present in every record type. Generic record operations |
|
12585 | 28 |
work on all possible extensions of a given type scheme; polymorphism |
29 |
takes care of structural sub-typing behind the scenes. There are |
|
30 |
also explicit coercion functions between fixed record types.% |
|
12572 | 31 |
\end{isamarkuptext}% |
32 |
\isamarkuptrue% |
|
33 |
% |
|
34 |
\isamarkupsubsection{Record Basics% |
|
35 |
} |
|
36 |
\isamarkuptrue% |
|
37 |
% |
|
38 |
\begin{isamarkuptext}% |
|
12585 | 39 |
Record types are not primitive in Isabelle and have a delicate |
12656 | 40 |
internal representation \cite{NaraschewskiW-TPHOLs98}, based on |
41 |
nested copies of the primitive product type. A \commdx{record} |
|
42 |
declaration introduces a new record type scheme by specifying its |
|
43 |
fields, which are packaged internally to hold up the perception of |
|
12700 | 44 |
the record as a distinguished entity. Here is a simple example:% |
12572 | 45 |
\end{isamarkuptext}% |
46 |
\isamarkuptrue% |
|
47 |
\isacommand{record}\ point\ {\isacharequal}\isanewline |
|
48 |
\ \ Xcoord\ {\isacharcolon}{\isacharcolon}\ int\isanewline |
|
49 |
\ \ Ycoord\ {\isacharcolon}{\isacharcolon}\ int\isamarkupfalse% |
|
50 |
% |
|
51 |
\begin{isamarkuptext}% |
|
52 |
Records of type \isa{point} have two fields named \isa{Xcoord} |
|
53 |
and \isa{Ycoord}, both of type~\isa{int}. We now define a |
|
54 |
constant of type \isa{point}:% |
|
55 |
\end{isamarkuptext}% |
|
56 |
\isamarkuptrue% |
|
57 |
\isacommand{constdefs}\isanewline |
|
58 |
\ \ pt{\isadigit{1}}\ {\isacharcolon}{\isacharcolon}\ point\isanewline |
|
59 |
\ \ {\isachardoublequote}pt{\isadigit{1}}\ {\isasymequiv}\ {\isacharparenleft}{\isacharbar}\ Xcoord\ {\isacharequal}\ {\isadigit{9}}{\isadigit{9}}{\isadigit{9}}{\isacharcomma}\ Ycoord\ {\isacharequal}\ {\isadigit{2}}{\isadigit{3}}\ {\isacharbar}{\isacharparenright}{\isachardoublequote}\isamarkupfalse% |
|
60 |
% |
|
61 |
\begin{isamarkuptext}% |
|
62 |
We see above the ASCII notation for record brackets. You can also |
|
63 |
use the symbolic brackets \isa{{\isasymlparr}} and \isa{{\isasymrparr}}. Record type |
|
12656 | 64 |
expressions can be also written directly with individual fields. |
12700 | 65 |
The type name above is merely an abbreviation.% |
12572 | 66 |
\end{isamarkuptext}% |
67 |
\isamarkuptrue% |
|
68 |
\isacommand{constdefs}\isanewline |
|
69 |
\ \ pt{\isadigit{2}}\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharcolon}\ int{\isacharcomma}\ Ycoord\ {\isacharcolon}{\isacharcolon}\ int{\isasymrparr}{\isachardoublequote}\isanewline |
|
70 |
\ \ {\isachardoublequote}pt{\isadigit{2}}\ {\isasymequiv}\ {\isasymlparr}Xcoord\ {\isacharequal}\ {\isacharminus}{\isadigit{4}}{\isadigit{5}}{\isacharcomma}\ Ycoord\ {\isacharequal}\ {\isadigit{9}}{\isadigit{7}}{\isasymrparr}{\isachardoublequote}\isamarkupfalse% |
|
71 |
% |
|
72 |
\begin{isamarkuptext}% |
|
12585 | 73 |
For each field, there is a \emph{selector}\index{selector!record} |
74 |
function of the same name. For example, if \isa{p} has type \isa{point} then \isa{Xcoord\ p} denotes the value of the \isa{Xcoord} field of~\isa{p}. Expressions involving field selection |
|
75 |
of explicit records are simplified automatically:% |
|
12572 | 76 |
\end{isamarkuptext}% |
77 |
\isamarkuptrue% |
|
78 |
\isacommand{lemma}\ {\isachardoublequote}Xcoord\ {\isasymlparr}Xcoord\ {\isacharequal}\ a{\isacharcomma}\ Ycoord\ {\isacharequal}\ b{\isasymrparr}\ {\isacharequal}\ a{\isachardoublequote}\isanewline |
|
79 |
\ \ \isamarkupfalse% |
|
80 |
\isacommand{by}\ simp\isamarkupfalse% |
|
81 |
% |
|
82 |
\begin{isamarkuptext}% |
|
12585 | 83 |
The \emph{update}\index{update!record} operation is functional. For |
84 |
example, \isa{p{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ {\isadigit{0}}{\isasymrparr}} is a record whose \isa{Xcoord} |
|
12656 | 85 |
value is zero and whose \isa{Ycoord} value is copied from~\isa{p}. Updates of explicit records are also simplified automatically:% |
12572 | 86 |
\end{isamarkuptext}% |
87 |
\isamarkuptrue% |
|
88 |
\isacommand{lemma}\ {\isachardoublequote}{\isasymlparr}Xcoord\ {\isacharequal}\ a{\isacharcomma}\ Ycoord\ {\isacharequal}\ b{\isasymrparr}{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ {\isadigit{0}}{\isasymrparr}\ {\isacharequal}\isanewline |
|
89 |
\ \ \ \ {\isasymlparr}Xcoord\ {\isacharequal}\ {\isadigit{0}}{\isacharcomma}\ Ycoord\ {\isacharequal}\ b{\isasymrparr}{\isachardoublequote}\isanewline |
|
90 |
\ \ \isamarkupfalse% |
|
91 |
\isacommand{by}\ simp\isamarkupfalse% |
|
92 |
% |
|
93 |
\begin{isamarkuptext}% |
|
94 |
\begin{warn} |
|
95 |
Field names are declared as constants and can no longer be used as |
|
96 |
variables. It would be unwise, for example, to call the fields of |
|
12585 | 97 |
type \isa{point} simply \isa{x} and~\isa{y}. |
12572 | 98 |
\end{warn}% |
99 |
\end{isamarkuptext}% |
|
100 |
\isamarkuptrue% |
|
101 |
% |
|
102 |
\isamarkupsubsection{Extensible Records and Generic Operations% |
|
103 |
} |
|
104 |
\isamarkuptrue% |
|
105 |
% |
|
106 |
\begin{isamarkuptext}% |
|
107 |
\index{records!extensible|(}% |
|
108 |
||
109 |
Now, let us define coloured points (type \isa{cpoint}) to be |
|
110 |
points extended with a field \isa{col} of type \isa{colour}:% |
|
111 |
\end{isamarkuptext}% |
|
112 |
\isamarkuptrue% |
|
113 |
\isacommand{datatype}\ colour\ {\isacharequal}\ Red\ {\isacharbar}\ Green\ {\isacharbar}\ Blue\isanewline |
|
114 |
\isanewline |
|
115 |
\isamarkupfalse% |
|
116 |
\isacommand{record}\ cpoint\ {\isacharequal}\ point\ {\isacharplus}\isanewline |
|
117 |
\ \ col\ {\isacharcolon}{\isacharcolon}\ colour\isamarkupfalse% |
|
118 |
% |
|
119 |
\begin{isamarkuptext}% |
|
120 |
The fields of this new type are \isa{Xcoord}, \isa{Ycoord} and |
|
12656 | 121 |
\isa{col}, in that order.% |
12572 | 122 |
\end{isamarkuptext}% |
123 |
\isamarkuptrue% |
|
124 |
\isacommand{constdefs}\isanewline |
|
125 |
\ \ cpt{\isadigit{1}}\ {\isacharcolon}{\isacharcolon}\ cpoint\isanewline |
|
126 |
\ \ {\isachardoublequote}cpt{\isadigit{1}}\ {\isasymequiv}\ {\isasymlparr}Xcoord\ {\isacharequal}\ {\isadigit{9}}{\isadigit{9}}{\isadigit{9}}{\isacharcomma}\ Ycoord\ {\isacharequal}\ {\isadigit{2}}{\isadigit{3}}{\isacharcomma}\ col\ {\isacharequal}\ Green{\isasymrparr}{\isachardoublequote}\isamarkupfalse% |
|
127 |
% |
|
128 |
\begin{isamarkuptext}% |
|
12658 | 129 |
\medskip We can define generic operations that work on arbitrary |
130 |
instances of a record scheme, e.g.\ covering \isa{point}, \isa{cpoint}, and any further extensions. Every record structure has an |
|
131 |
implicit pseudo-field, \cdx{more}, that keeps the extension as an |
|
132 |
explicit value. Its type is declared as completely |
|
133 |
polymorphic:~\isa{{\isacharprime}a}. When a fixed record value is expressed |
|
134 |
using just its standard fields, the value of \isa{more} is |
|
135 |
implicitly set to \isa{{\isacharparenleft}{\isacharparenright}}, the empty tuple, which has type |
|
136 |
\isa{unit}. Within the record brackets, you can refer to the |
|
137 |
\isa{more} field by writing ``\isa{{\isasymdots}}'' (three dots):% |
|
12572 | 138 |
\end{isamarkuptext}% |
139 |
\isamarkuptrue% |
|
140 |
\isacommand{lemma}\ {\isachardoublequote}Xcoord\ {\isasymlparr}Xcoord\ {\isacharequal}\ a{\isacharcomma}\ Ycoord\ {\isacharequal}\ b{\isacharcomma}\ {\isasymdots}\ {\isacharequal}\ p{\isasymrparr}\ {\isacharequal}\ a{\isachardoublequote}\isanewline |
|
141 |
\ \ \isamarkupfalse% |
|
142 |
\isacommand{by}\ simp\isamarkupfalse% |
|
143 |
% |
|
144 |
\begin{isamarkuptext}% |
|
12656 | 145 |
This lemma applies to any record whose first two fields are \isa{Xcoord} and~\isa{Ycoord}. Note that \isa{{\isasymlparr}Xcoord\ {\isacharequal}\ a{\isacharcomma}\ Ycoord\ {\isacharequal}\ b{\isacharcomma}\ {\isasymdots}\ {\isacharequal}\ {\isacharparenleft}{\isacharparenright}{\isasymrparr}} is exactly the same as \isa{{\isasymlparr}Xcoord\ {\isacharequal}\ a{\isacharcomma}\ Ycoord\ {\isacharequal}\ b{\isasymrparr}}. Selectors and updates are always polymorphic wrt.\ the |
146 |
\isa{more} part of a record scheme, its value is just ignored (for |
|
12585 | 147 |
select) or copied (for update). |
12572 | 148 |
|
12585 | 149 |
The \isa{more} pseudo-field may be manipulated directly as well, |
150 |
but the identifier needs to be qualified:% |
|
12572 | 151 |
\end{isamarkuptext}% |
152 |
\isamarkuptrue% |
|
153 |
\isacommand{lemma}\ {\isachardoublequote}point{\isachardot}more\ cpt{\isadigit{1}}\ {\isacharequal}\ {\isasymlparr}col\ {\isacharequal}\ Green{\isasymrparr}{\isachardoublequote}\isanewline |
|
154 |
\ \ \isamarkupfalse% |
|
155 |
\isacommand{by}\ {\isacharparenleft}simp\ add{\isacharcolon}\ cpt{\isadigit{1}}{\isacharunderscore}def{\isacharparenright}\isamarkupfalse% |
|
156 |
% |
|
157 |
\begin{isamarkuptext}% |
|
12656 | 158 |
We see that the colour part attached to this \isa{point} is a |
12700 | 159 |
rudimentary record in its own right, namely \isa{{\isasymlparr}col\ {\isacharequal}\ Green{\isasymrparr}}. In order to select or update \isa{col}, this fragment |
12585 | 160 |
needs to be put back into the context of the parent type scheme, say |
161 |
as \isa{more} part of another \isa{point}. |
|
12572 | 162 |
|
163 |
To define generic operations, we need to know a bit more about |
|
12656 | 164 |
records. Our definition of \isa{point} above has generated two |
165 |
type abbreviations: |
|
12572 | 166 |
|
12585 | 167 |
\medskip |
12572 | 168 |
\begin{tabular}{l} |
14270 | 169 |
\isa{point}~\isa{{\isacharequal}}~\isa{point} \\ |
170 |
\isa{{\isacharprime}a\ point{\isacharunderscore}scheme}~\isa{{\isacharequal}}~\isa{{\isacharprime}a\ point{\isacharunderscore}scheme} \\ |
|
12572 | 171 |
\end{tabular} |
12585 | 172 |
\medskip |
12572 | 173 |
|
12585 | 174 |
Type \isa{point} is for fixed records having exactly the two fields |
12572 | 175 |
\isa{Xcoord} and~\isa{Ycoord}, while the polymorphic type \isa{{\isacharprime}a\ point{\isacharunderscore}scheme} comprises all possible extensions to those two |
12585 | 176 |
fields. Note that \isa{unit\ point{\isacharunderscore}scheme} coincides with \isa{point}, and \isa{{\isasymlparr}col\ {\isacharcolon}{\isacharcolon}\ colour{\isasymrparr}\ point{\isacharunderscore}scheme} with \isa{cpoint}. |
177 |
||
178 |
In the following example we define two operations --- methods, if we |
|
179 |
regard records as objects --- to get and set any point's \isa{Xcoord} field.% |
|
12572 | 180 |
\end{isamarkuptext}% |
181 |
\isamarkuptrue% |
|
182 |
\isacommand{constdefs}\isanewline |
|
183 |
\ \ getX\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}{\isacharprime}a\ point{\isacharunderscore}scheme\ {\isasymRightarrow}\ int{\isachardoublequote}\isanewline |
|
184 |
\ \ {\isachardoublequote}getX\ r\ {\isasymequiv}\ Xcoord\ r{\isachardoublequote}\isanewline |
|
185 |
\ \ setX\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}{\isacharprime}a\ point{\isacharunderscore}scheme\ {\isasymRightarrow}\ int\ {\isasymRightarrow}\ {\isacharprime}a\ point{\isacharunderscore}scheme{\isachardoublequote}\isanewline |
|
186 |
\ \ {\isachardoublequote}setX\ r\ a\ {\isasymequiv}\ r{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ a{\isasymrparr}{\isachardoublequote}\isamarkupfalse% |
|
187 |
% |
|
188 |
\begin{isamarkuptext}% |
|
189 |
Here is a generic method that modifies a point, incrementing its |
|
190 |
\isa{Xcoord} field. The \isa{Ycoord} and \isa{more} fields |
|
191 |
are copied across. It works for any record type scheme derived from |
|
12585 | 192 |
\isa{point} (including \isa{cpoint} etc.):% |
12572 | 193 |
\end{isamarkuptext}% |
194 |
\isamarkuptrue% |
|
195 |
\isacommand{constdefs}\isanewline |
|
196 |
\ \ incX\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}{\isacharprime}a\ point{\isacharunderscore}scheme\ {\isasymRightarrow}\ {\isacharprime}a\ point{\isacharunderscore}scheme{\isachardoublequote}\isanewline |
|
12656 | 197 |
\ \ {\isachardoublequote}incX\ r\ {\isasymequiv}\isanewline |
198 |
\ \ \ \ {\isasymlparr}Xcoord\ {\isacharequal}\ Xcoord\ r\ {\isacharplus}\ {\isadigit{1}}{\isacharcomma}\ Ycoord\ {\isacharequal}\ Ycoord\ r{\isacharcomma}\ {\isasymdots}\ {\isacharequal}\ point{\isachardot}more\ r{\isasymrparr}{\isachardoublequote}\isamarkupfalse% |
|
12572 | 199 |
% |
200 |
\begin{isamarkuptext}% |
|
201 |
Generic theorems can be proved about generic methods. This trivial |
|
202 |
lemma relates \isa{incX} to \isa{getX} and \isa{setX}:% |
|
203 |
\end{isamarkuptext}% |
|
204 |
\isamarkuptrue% |
|
205 |
\isacommand{lemma}\ {\isachardoublequote}incX\ r\ {\isacharequal}\ setX\ r\ {\isacharparenleft}getX\ r\ {\isacharplus}\ {\isadigit{1}}{\isacharparenright}{\isachardoublequote}\isanewline |
|
206 |
\ \ \isamarkupfalse% |
|
207 |
\isacommand{by}\ {\isacharparenleft}simp\ add{\isacharcolon}\ getX{\isacharunderscore}def\ setX{\isacharunderscore}def\ incX{\isacharunderscore}def{\isacharparenright}\isamarkupfalse% |
|
208 |
% |
|
209 |
\begin{isamarkuptext}% |
|
210 |
\begin{warn} |
|
211 |
If you use the symbolic record brackets \isa{{\isasymlparr}} and \isa{{\isasymrparr}}, |
|
212 |
then you must also use the symbolic ellipsis, ``\isa{{\isasymdots}}'', rather |
|
213 |
than three consecutive periods, ``\isa{{\isachardot}{\isachardot}{\isachardot}}''. Mixing the ASCII |
|
214 |
and symbolic versions causes a syntax error. (The two versions are |
|
215 |
more distinct on screen than they are on paper.) |
|
12634 | 216 |
\end{warn}% |
217 |
\index{records!extensible|)}% |
|
12572 | 218 |
\end{isamarkuptext}% |
219 |
\isamarkuptrue% |
|
220 |
% |
|
221 |
\isamarkupsubsection{Record Equality% |
|
222 |
} |
|
223 |
\isamarkuptrue% |
|
224 |
% |
|
225 |
\begin{isamarkuptext}% |
|
226 |
Two records are equal\index{equality!of records} if all pairs of |
|
12656 | 227 |
corresponding fields are equal. Concrete record equalities are |
228 |
simplified automatically:% |
|
12572 | 229 |
\end{isamarkuptext}% |
230 |
\isamarkuptrue% |
|
231 |
\isacommand{lemma}\ {\isachardoublequote}{\isacharparenleft}{\isasymlparr}Xcoord\ {\isacharequal}\ a{\isacharcomma}\ Ycoord\ {\isacharequal}\ b{\isasymrparr}\ {\isacharequal}\ {\isasymlparr}Xcoord\ {\isacharequal}\ a{\isacharprime}{\isacharcomma}\ Ycoord\ {\isacharequal}\ b{\isacharprime}{\isasymrparr}{\isacharparenright}\ {\isacharequal}\isanewline |
|
232 |
\ \ \ \ {\isacharparenleft}a\ {\isacharequal}\ a{\isacharprime}\ {\isasymand}\ b\ {\isacharequal}\ b{\isacharprime}{\isacharparenright}{\isachardoublequote}\isanewline |
|
233 |
\ \ \isamarkupfalse% |
|
234 |
\isacommand{by}\ simp\isamarkupfalse% |
|
235 |
% |
|
236 |
\begin{isamarkuptext}% |
|
237 |
The following equality is similar, but generic, in that \isa{r} |
|
12585 | 238 |
can be any instance of \isa{{\isacharprime}a\ point{\isacharunderscore}scheme}:% |
12572 | 239 |
\end{isamarkuptext}% |
240 |
\isamarkuptrue% |
|
241 |
\isacommand{lemma}\ {\isachardoublequote}r{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ a{\isacharcomma}\ Ycoord\ {\isacharcolon}{\isacharequal}\ b{\isasymrparr}\ {\isacharequal}\ r{\isasymlparr}Ycoord\ {\isacharcolon}{\isacharequal}\ b{\isacharcomma}\ Xcoord\ {\isacharcolon}{\isacharequal}\ a{\isasymrparr}{\isachardoublequote}\isanewline |
|
242 |
\ \ \isamarkupfalse% |
|
243 |
\isacommand{by}\ simp\isamarkupfalse% |
|
244 |
% |
|
245 |
\begin{isamarkuptext}% |
|
246 |
We see above the syntax for iterated updates. We could equivalently |
|
12585 | 247 |
have written the left-hand side as \isa{r{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ a{\isasymrparr}{\isasymlparr}Ycoord\ {\isacharcolon}{\isacharequal}\ b{\isasymrparr}}. |
12572 | 248 |
|
12585 | 249 |
\medskip Record equality is \emph{extensional}: |
250 |
\index{extensionality!for records} a record is determined entirely |
|
251 |
by the values of its fields.% |
|
12572 | 252 |
\end{isamarkuptext}% |
253 |
\isamarkuptrue% |
|
254 |
\isacommand{lemma}\ {\isachardoublequote}r\ {\isacharequal}\ {\isasymlparr}Xcoord\ {\isacharequal}\ Xcoord\ r{\isacharcomma}\ Ycoord\ {\isacharequal}\ Ycoord\ r{\isasymrparr}{\isachardoublequote}\isanewline |
|
255 |
\ \ \isamarkupfalse% |
|
256 |
\isacommand{by}\ simp\isamarkupfalse% |
|
257 |
% |
|
258 |
\begin{isamarkuptext}% |
|
12585 | 259 |
The generic version of this equality includes the pseudo-field |
260 |
\isa{more}:% |
|
12572 | 261 |
\end{isamarkuptext}% |
262 |
\isamarkuptrue% |
|
263 |
\isacommand{lemma}\ {\isachardoublequote}r\ {\isacharequal}\ {\isasymlparr}Xcoord\ {\isacharequal}\ Xcoord\ r{\isacharcomma}\ Ycoord\ {\isacharequal}\ Ycoord\ r{\isacharcomma}\ {\isasymdots}\ {\isacharequal}\ point{\isachardot}more\ r{\isasymrparr}{\isachardoublequote}\isanewline |
|
264 |
\ \ \isamarkupfalse% |
|
265 |
\isacommand{by}\ simp\isamarkupfalse% |
|
266 |
% |
|
267 |
\begin{isamarkuptext}% |
|
12585 | 268 |
\medskip The simplifier can prove many record equalities |
12572 | 269 |
automatically, but general equality reasoning can be tricky. |
270 |
Consider proving this obvious fact:% |
|
271 |
\end{isamarkuptext}% |
|
272 |
\isamarkuptrue% |
|
273 |
\isacommand{lemma}\ {\isachardoublequote}r{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ a{\isasymrparr}\ {\isacharequal}\ r{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ a{\isacharprime}{\isasymrparr}\ {\isasymLongrightarrow}\ a\ {\isacharequal}\ a{\isacharprime}{\isachardoublequote}\isanewline |
|
274 |
\ \ \isamarkupfalse% |
|
275 |
\isacommand{apply}\ simp{\isacharquery}\isanewline |
|
276 |
\ \ \isamarkupfalse% |
|
277 |
\isacommand{oops}\isamarkupfalse% |
|
278 |
% |
|
279 |
\begin{isamarkuptext}% |
|
12585 | 280 |
Here the simplifier can do nothing, since general record equality is |
281 |
not eliminated automatically. One way to proceed is by an explicit |
|
12572 | 282 |
forward step that applies the selector \isa{Xcoord} to both sides |
283 |
of the assumed record equality:% |
|
284 |
\end{isamarkuptext}% |
|
285 |
\isamarkuptrue% |
|
286 |
\isacommand{lemma}\ {\isachardoublequote}r{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ a{\isasymrparr}\ {\isacharequal}\ r{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ a{\isacharprime}{\isasymrparr}\ {\isasymLongrightarrow}\ a\ {\isacharequal}\ a{\isacharprime}{\isachardoublequote}\isanewline |
|
287 |
\ \ \isamarkupfalse% |
|
288 |
\isacommand{apply}\ {\isacharparenleft}drule{\isacharunderscore}tac\ f\ {\isacharequal}\ Xcoord\ \isakeyword{in}\ arg{\isacharunderscore}cong{\isacharparenright}\isamarkupfalse% |
|
289 |
% |
|
290 |
\begin{isamarkuptxt}% |
|
291 |
\begin{isabelle}% |
|
292 |
\ {\isadigit{1}}{\isachardot}\ Xcoord\ {\isacharparenleft}r{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ a{\isasymrparr}{\isacharparenright}\ {\isacharequal}\ Xcoord\ {\isacharparenleft}r{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ a{\isacharprime}{\isasymrparr}{\isacharparenright}\ {\isasymLongrightarrow}\ a\ {\isacharequal}\ a{\isacharprime}% |
|
293 |
\end{isabelle} |
|
294 |
Now, \isa{simp} will reduce the assumption to the desired |
|
295 |
conclusion.% |
|
296 |
\end{isamarkuptxt}% |
|
297 |
\ \ \isamarkuptrue% |
|
298 |
\isacommand{apply}\ simp\isanewline |
|
299 |
\ \ \isamarkupfalse% |
|
300 |
\isacommand{done}\isamarkupfalse% |
|
301 |
% |
|
302 |
\begin{isamarkuptext}% |
|
12585 | 303 |
The \isa{cases} method is preferable to such a forward proof. We |
304 |
state the desired lemma again:% |
|
12572 | 305 |
\end{isamarkuptext}% |
306 |
\isamarkuptrue% |
|
307 |
\isacommand{lemma}\ {\isachardoublequote}r{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ a{\isasymrparr}\ {\isacharequal}\ r{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ a{\isacharprime}{\isasymrparr}\ {\isasymLongrightarrow}\ a\ {\isacharequal}\ a{\isacharprime}{\isachardoublequote}\isamarkupfalse% |
|
308 |
% |
|
309 |
\begin{isamarkuptxt}% |
|
12585 | 310 |
The \methdx{cases} method adds an equality to replace the |
311 |
named record term by an explicit record expression, listing all |
|
312 |
fields. It even includes the pseudo-field \isa{more}, since the |
|
313 |
record equality stated here is generic for all extensions.% |
|
12572 | 314 |
\end{isamarkuptxt}% |
315 |
\ \ \isamarkuptrue% |
|
316 |
\isacommand{apply}\ {\isacharparenleft}cases\ r{\isacharparenright}\isamarkupfalse% |
|
317 |
% |
|
318 |
\begin{isamarkuptxt}% |
|
319 |
\begin{isabelle}% |
|
320 |
\ {\isadigit{1}}{\isachardot}\ {\isasymAnd}Xcoord\ Ycoord\ more{\isachardot}\isanewline |
|
321 |
\isaindent{\ {\isadigit{1}}{\isachardot}\ \ \ \ }{\isasymlbrakk}r{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ a{\isasymrparr}\ {\isacharequal}\ r{\isasymlparr}Xcoord\ {\isacharcolon}{\isacharequal}\ a{\isacharprime}{\isasymrparr}{\isacharsemicolon}\isanewline |
|
14379 | 322 |
\isaindent{\ {\isadigit{1}}{\isachardot}\ \ \ \ \ }r\ {\isacharequal}\ {\isasymlparr}Xcoord\ {\isacharequal}\ Xcoord{\isacharcomma}\ Ycoord\ {\isacharequal}\ Ycoord{\isacharcomma}\ {\isasymdots}\ {\isacharequal}\ more{\isasymrparr}{\isasymrbrakk}\isanewline |
12572 | 323 |
\isaindent{\ {\isadigit{1}}{\isachardot}\ \ \ \ }{\isasymLongrightarrow}\ a\ {\isacharequal}\ a{\isacharprime}% |
12585 | 324 |
\end{isabelle} Again, \isa{simp} finishes the proof. Because \isa{r} is now represented as |
325 |
an explicit record construction, the updates can be applied and the |
|
326 |
record equality can be replaced by equality of the corresponding |
|
327 |
fields (due to injectivity).% |
|
12572 | 328 |
\end{isamarkuptxt}% |
329 |
\ \ \isamarkuptrue% |
|
330 |
\isacommand{apply}\ simp\isanewline |
|
331 |
\ \ \isamarkupfalse% |
|
332 |
\isacommand{done}\isamarkupfalse% |
|
333 |
% |
|
12585 | 334 |
\begin{isamarkuptext}% |
335 |
The generic cases method does not admit references to locally bound |
|
336 |
parameters of a goal. In longer proof scripts one might have to |
|
337 |
fall back on the primitive \isa{rule{\isacharunderscore}tac} used together with the |
|
12658 | 338 |
internal field representation rules of records. The above use of |
339 |
\isa{{\isacharparenleft}cases\ r{\isacharparenright}} would become \isa{{\isacharparenleft}rule{\isacharunderscore}tac\ r\ {\isacharequal}\ r\ in\ point{\isachardot}cases{\isacharunderscore}scheme{\isacharparenright}}.% |
|
12585 | 340 |
\end{isamarkuptext}% |
341 |
\isamarkuptrue% |
|
342 |
% |
|
12572 | 343 |
\isamarkupsubsection{Extending and Truncating Records% |
344 |
} |
|
345 |
\isamarkuptrue% |
|
346 |
% |
|
347 |
\begin{isamarkuptext}% |
|
12585 | 348 |
Each record declaration introduces a number of derived operations to |
349 |
refer collectively to a record's fields and to convert between fixed |
|
350 |
record types. They can, for instance, convert between types \isa{point} and \isa{cpoint}. We can add a colour to a point or convert |
|
351 |
a \isa{cpoint} to a \isa{point} by forgetting its colour. |
|
12572 | 352 |
|
353 |
\begin{itemize} |
|
354 |
||
355 |
\item Function \cdx{make} takes as arguments all of the record's |
|
12585 | 356 |
fields (including those inherited from ancestors). It returns the |
357 |
corresponding record. |
|
12572 | 358 |
|
12585 | 359 |
\item Function \cdx{fields} takes the record's very own fields and |
12572 | 360 |
returns a record fragment consisting of just those fields. This may |
361 |
be filled into the \isa{more} part of the parent record scheme. |
|
362 |
||
363 |
\item Function \cdx{extend} takes two arguments: a record to be |
|
364 |
extended and a record containing the new fields. |
|
365 |
||
366 |
\item Function \cdx{truncate} takes a record (possibly an extension |
|
367 |
of the original record type) and returns a fixed record, removing |
|
368 |
any additional fields. |
|
369 |
||
370 |
\end{itemize} |
|
371 |
||
12700 | 372 |
These functions provide useful abbreviations for standard |
12572 | 373 |
record expressions involving constructors and selectors. The |
374 |
definitions, which are \emph{not} unfolded by default, are made |
|
12585 | 375 |
available by the collective name of \isa{defs} (\isa{point{\isachardot}defs}, \isa{cpoint{\isachardot}defs}, etc.). |
12572 | 376 |
|
377 |
For example, here are the versions of those functions generated for |
|
378 |
record \isa{point}. We omit \isa{point{\isachardot}fields}, which happens to |
|
379 |
be the same as \isa{point{\isachardot}make}. |
|
380 |
||
381 |
\begin{isabelle}% |
|
14353
79f9fbef9106
Added lemmas to Ring_and_Field with slightly modified simplification rules
paulson
parents:
14270
diff
changeset
|
382 |
point{\isachardot}make\ Xcoord\ Ycoord\ {\isasymequiv}\ {\isasymlparr}Xcoord\ {\isacharequal}\ Xcoord{\isacharcomma}\ Ycoord\ {\isacharequal}\ Ycoord{\isasymrparr}\isasep\isanewline% |
12585 | 383 |
point{\isachardot}extend\ r\ more\ {\isasymequiv}\isanewline |
14353
79f9fbef9106
Added lemmas to Ring_and_Field with slightly modified simplification rules
paulson
parents:
14270
diff
changeset
|
384 |
{\isasymlparr}Xcoord\ {\isacharequal}\ Xcoord\ r{\isacharcomma}\ Ycoord\ {\isacharequal}\ Ycoord\ r{\isacharcomma}\ {\isasymdots}\ {\isacharequal}\ more{\isasymrparr}\isasep\isanewline% |
12585 | 385 |
point{\isachardot}truncate\ r\ {\isasymequiv}\ {\isasymlparr}Xcoord\ {\isacharequal}\ Xcoord\ r{\isacharcomma}\ Ycoord\ {\isacharequal}\ Ycoord\ r{\isasymrparr}% |
12572 | 386 |
\end{isabelle} |
387 |
||
388 |
Contrast those with the corresponding functions for record \isa{cpoint}. Observe \isa{cpoint{\isachardot}fields} in particular. |
|
389 |
||
390 |
\begin{isabelle}% |
|
12585 | 391 |
cpoint{\isachardot}make\ Xcoord\ Ycoord\ col\ {\isasymequiv}\isanewline |
14353
79f9fbef9106
Added lemmas to Ring_and_Field with slightly modified simplification rules
paulson
parents:
14270
diff
changeset
|
392 |
{\isasymlparr}Xcoord\ {\isacharequal}\ Xcoord{\isacharcomma}\ Ycoord\ {\isacharequal}\ Ycoord{\isacharcomma}\ col\ {\isacharequal}\ col{\isasymrparr}\isasep\isanewline% |
79f9fbef9106
Added lemmas to Ring_and_Field with slightly modified simplification rules
paulson
parents:
14270
diff
changeset
|
393 |
cpoint{\isachardot}fields\ col\ {\isasymequiv}\ {\isasymlparr}col\ {\isacharequal}\ col{\isasymrparr}\isasep\isanewline% |
12585 | 394 |
cpoint{\isachardot}extend\ r\ more\ {\isasymequiv}\isanewline |
14353
79f9fbef9106
Added lemmas to Ring_and_Field with slightly modified simplification rules
paulson
parents:
14270
diff
changeset
|
395 |
{\isasymlparr}Xcoord\ {\isacharequal}\ Xcoord\ r{\isacharcomma}\ Ycoord\ {\isacharequal}\ Ycoord\ r{\isacharcomma}\ col\ {\isacharequal}\ col\ r{\isacharcomma}\ {\isasymdots}\ {\isacharequal}\ more{\isasymrparr}\isasep\isanewline% |
12585 | 396 |
cpoint{\isachardot}truncate\ r\ {\isasymequiv}\isanewline |
397 |
{\isasymlparr}Xcoord\ {\isacharequal}\ Xcoord\ r{\isacharcomma}\ Ycoord\ {\isacharequal}\ Ycoord\ r{\isacharcomma}\ col\ {\isacharequal}\ col\ r{\isasymrparr}% |
|
12572 | 398 |
\end{isabelle} |
399 |
||
400 |
To demonstrate these functions, we declare a new coloured point by |
|
401 |
extending an ordinary point. Function \isa{point{\isachardot}extend} augments |
|
12585 | 402 |
\isa{pt{\isadigit{1}}} with a colour value, which is converted into an |
403 |
appropriate record fragment by \isa{cpoint{\isachardot}fields}.% |
|
12572 | 404 |
\end{isamarkuptext}% |
405 |
\isamarkuptrue% |
|
406 |
\isacommand{constdefs}\isanewline |
|
407 |
\ \ cpt{\isadigit{2}}\ {\isacharcolon}{\isacharcolon}\ cpoint\isanewline |
|
408 |
\ \ {\isachardoublequote}cpt{\isadigit{2}}\ {\isasymequiv}\ point{\isachardot}extend\ pt{\isadigit{1}}\ {\isacharparenleft}cpoint{\isachardot}fields\ Green{\isacharparenright}{\isachardoublequote}\isamarkupfalse% |
|
409 |
% |
|
410 |
\begin{isamarkuptext}% |
|
411 |
The coloured points \isa{cpt{\isadigit{1}}} and \isa{cpt{\isadigit{2}}} are equal. The |
|
412 |
proof is trivial, by unfolding all the definitions. We deliberately |
|
413 |
omit the definition of~\isa{pt{\isadigit{1}}} in order to reveal the underlying |
|
414 |
comparison on type \isa{point}.% |
|
415 |
\end{isamarkuptext}% |
|
416 |
\isamarkuptrue% |
|
417 |
\isacommand{lemma}\ {\isachardoublequote}cpt{\isadigit{1}}\ {\isacharequal}\ cpt{\isadigit{2}}{\isachardoublequote}\isanewline |
|
418 |
\ \ \isamarkupfalse% |
|
419 |
\isacommand{apply}\ {\isacharparenleft}simp\ add{\isacharcolon}\ cpt{\isadigit{1}}{\isacharunderscore}def\ cpt{\isadigit{2}}{\isacharunderscore}def\ point{\isachardot}defs\ cpoint{\isachardot}defs{\isacharparenright}\isamarkupfalse% |
|
420 |
% |
|
421 |
\begin{isamarkuptxt}% |
|
422 |
\begin{isabelle}% |
|
423 |
\ {\isadigit{1}}{\isachardot}\ Xcoord\ pt{\isadigit{1}}\ {\isacharequal}\ {\isadigit{9}}{\isadigit{9}}{\isadigit{9}}\ {\isasymand}\ Ycoord\ pt{\isadigit{1}}\ {\isacharequal}\ {\isadigit{2}}{\isadigit{3}}% |
|
424 |
\end{isabelle}% |
|
425 |
\end{isamarkuptxt}% |
|
426 |
\ \ \isamarkuptrue% |
|
427 |
\isacommand{apply}\ {\isacharparenleft}simp\ add{\isacharcolon}\ pt{\isadigit{1}}{\isacharunderscore}def{\isacharparenright}\isanewline |
|
428 |
\ \ \isamarkupfalse% |
|
429 |
\isacommand{done}\isamarkupfalse% |
|
430 |
% |
|
431 |
\begin{isamarkuptext}% |
|
432 |
In the example below, a coloured point is truncated to leave a |
|
12585 | 433 |
point. We use the \isa{truncate} function of the target record.% |
12572 | 434 |
\end{isamarkuptext}% |
435 |
\isamarkuptrue% |
|
436 |
\isacommand{lemma}\ {\isachardoublequote}point{\isachardot}truncate\ cpt{\isadigit{2}}\ {\isacharequal}\ pt{\isadigit{1}}{\isachardoublequote}\isanewline |
|
437 |
\ \ \isamarkupfalse% |
|
438 |
\isacommand{by}\ {\isacharparenleft}simp\ add{\isacharcolon}\ pt{\isadigit{1}}{\isacharunderscore}def\ cpt{\isadigit{2}}{\isacharunderscore}def\ point{\isachardot}defs{\isacharparenright}\isamarkupfalse% |
|
439 |
% |
|
440 |
\begin{isamarkuptext}% |
|
441 |
\begin{exercise} |
|
12585 | 442 |
Extend record \isa{cpoint} to have a further field, \isa{intensity}, of type~\isa{nat}. Experiment with generic operations |
443 |
(using polymorphic selectors and updates) and explicit coercions |
|
444 |
(using \isa{extend}, \isa{truncate} etc.) among the three record |
|
445 |
types. |
|
12572 | 446 |
\end{exercise} |
447 |
||
448 |
\begin{exercise} |
|
449 |
(For Java programmers.) |
|
450 |
Model a small class hierarchy using records. |
|
451 |
\end{exercise} |
|
452 |
\index{records|)}% |
|
453 |
\end{isamarkuptext}% |
|
454 |
\isamarkuptrue% |
|
455 |
\isamarkupfalse% |
|
456 |
\end{isabellebody}% |
|
457 |
%%% Local Variables: |
|
458 |
%%% mode: latex |
|
459 |
%%% TeX-master: "root" |
|
460 |
%%% End: |