68 *} |
68 *} |
69 |
69 |
70 text %quote {*@{code_stmts fib (consts) fib fib_step (Haskell)}*} |
70 text %quote {*@{code_stmts fib (consts) fib fib_step (Haskell)}*} |
71 |
71 |
72 |
72 |
73 subsection {* Datatypes \label{sec:datatypes} *} |
73 subsection {* Datatype refinement *} |
74 |
74 |
75 text {* |
75 text {* |
76 Conceptually, any datatype is spanned by a set of |
76 Selecting specific code equations \emph{and} datatype constructors |
77 \emph{constructors} of type @{text "\<tau> = \<dots> \<Rightarrow> \<kappa> \<alpha>\<^isub>1 \<dots> \<alpha>\<^isub>n"} where @{text |
77 leads to datatype refinement. As an example, we will develop an |
78 "{\<alpha>\<^isub>1, \<dots>, \<alpha>\<^isub>n}"} is exactly the set of \emph{all} type variables in |
78 alternative representation of the queue example given in |
79 @{text "\<tau>"}. The HOL datatype package by default registers any new |
79 \secref{sec:queue_example}. The amortised representation is |
80 datatype in the table of datatypes, which may be inspected using the |
80 convenient for generating code but exposes its \qt{implementation} |
81 @{command print_codesetup} command. |
81 details, which may be cumbersome when proving theorems about it. |
82 |
82 Therefore, here is a simple, straightforward representation of |
83 In some cases, it is appropriate to alter or extend this table. As |
83 queues: |
84 an example, we will develop an alternative representation of the |
|
85 queue example given in \secref{sec:queue_example}. The amortised |
|
86 representation is convenient for generating code but exposes its |
|
87 \qt{implementation} details, which may be cumbersome when proving |
|
88 theorems about it. Therefore, here is a simple, straightforward |
|
89 representation of queues: |
|
90 *} |
84 *} |
91 |
85 |
92 datatype %quote 'a queue = Queue "'a list" |
86 datatype %quote 'a queue = Queue "'a list" |
93 |
87 |
94 definition %quote empty :: "'a queue" where |
88 definition %quote empty :: "'a queue" where |
113 |
107 |
114 text {* |
108 text {* |
115 \noindent Here we define a \qt{constructor} @{const "AQueue"} which |
109 \noindent Here we define a \qt{constructor} @{const "AQueue"} which |
116 is defined in terms of @{text "Queue"} and interprets its arguments |
110 is defined in terms of @{text "Queue"} and interprets its arguments |
117 according to what the \emph{content} of an amortised queue is supposed |
111 according to what the \emph{content} of an amortised queue is supposed |
118 to be. Equipped with this, we are able to prove the following equations |
112 to be. |
|
113 |
|
114 The prerequisite for datatype constructors is only syntactical: a |
|
115 constructor must be of type @{text "\<tau> = \<dots> \<Rightarrow> \<kappa> \<alpha>\<^isub>1 \<dots> \<alpha>\<^isub>n"} where @{text |
|
116 "{\<alpha>\<^isub>1, \<dots>, \<alpha>\<^isub>n}"} is exactly the set of \emph{all} type variables in |
|
117 @{text "\<tau>"}; then @{text "\<kappa>"} is its corresponding datatype. The |
|
118 HOL datatype package by default registers any new datatype with its |
|
119 constructors, but this may be changed using @{command |
|
120 code_datatype}; the currently chosen constructors can be inspected |
|
121 using the @{command print_codesetup} command. |
|
122 |
|
123 Equipped with this, we are able to prove the following equations |
119 for our primitive queue operations which \qt{implement} the simple |
124 for our primitive queue operations which \qt{implement} the simple |
120 queues in an amortised fashion: |
125 queues in an amortised fashion: |
121 *} |
126 *} |
122 |
127 |
123 lemma %quote empty_AQueue [code]: |
128 lemma %quote empty_AQueue [code]: |
149 *} |
154 *} |
150 |
155 |
151 text %quote {*@{code_stmts empty enqueue dequeue (SML)}*} |
156 text %quote {*@{code_stmts empty enqueue dequeue (SML)}*} |
152 |
157 |
153 text {* |
158 text {* |
154 \noindent From this example, it can be glimpsed that using own |
159 The same techniques can also be applied to types which are not |
155 constructor sets is a little delicate since it changes the set of |
160 specified as datatypes, e.g.~type @{typ int} is originally specified |
156 valid patterns for values of that type. Without going into much |
161 as quotient type by means of @{command typedef}, but for code |
157 detail, here some practical hints: |
162 generation constants allowing construction of binary numeral values |
|
163 are used as constructors for @{typ int}. |
158 |
164 |
159 \begin{itemize} |
165 This approach however fails if the representation of a type demands |
|
166 invariants; this issue is discussed in the next section. |
|
167 *} |
160 |
168 |
161 \item When changing the constructor set for datatypes, take care |
|
162 to provide alternative equations for the @{text case} combinator. |
|
163 |
169 |
164 \item Values in the target language need not to be normalised -- |
170 subsection {* Datatype refinement involving invariants *} |
165 different values in the target language may represent the same |
|
166 value in the logic. |
|
167 |
171 |
168 \item Usually, a good methodology to deal with the subtleties of |
172 text {* |
169 pattern matching is to see the type as an abstract type: provide |
173 FIXME |
170 a set of operations which operate on the concrete representation |
|
171 of the type, and derive further operations by combinations of |
|
172 these primitive ones, without relying on a particular |
|
173 representation. |
|
174 |
|
175 \end{itemize} |
|
176 *} |
174 *} |
177 |
175 |
178 end |
176 end |