1869 case}, to ensure that the new types are non-empty. If there are nested |
1869 case}, to ensure that the new types are non-empty. If there are nested |
1870 occurrences, a datatype can even be non-empty without having a base case |
1870 occurrences, a datatype can even be non-empty without having a base case |
1871 itself. Since \texttt{list} is a non-empty datatype, \texttt{datatype t = C (t |
1871 itself. Since \texttt{list} is a non-empty datatype, \texttt{datatype t = C (t |
1872 list)} is non-empty as well. |
1872 list)} is non-empty as well. |
1873 |
1873 |
|
1874 |
|
1875 \subsubsection{Freeness of the constructors} |
|
1876 |
1874 The datatype constructors are automatically defined as functions of their |
1877 The datatype constructors are automatically defined as functions of their |
1875 respective type: |
1878 respective type: |
1876 \[ C^j@i :: [\tau^j@{i,1},\dots,\tau^j@{i,m^j@i}] \To (\alpha@1,\dots,\alpha@h)t@j \] |
1879 \[ C^j@i :: [\tau^j@{i,1},\dots,\tau^j@{i,m^j@i}] \To (\alpha@1,\dots,\alpha@h)t@j \] |
1877 These functions have certain {\em freeness} properties. They are distinct: |
1880 These functions have certain {\em freeness} properties. They construct |
|
1881 distinct values: |
1878 \[ |
1882 \[ |
1879 C^j@i~x@1~\dots~x@{m^j@i} \neq C^j@{i'}~y@1~\dots~y@{m^j@{i'}} \qquad |
1883 C^j@i~x@1~\dots~x@{m^j@i} \neq C^j@{i'}~y@1~\dots~y@{m^j@{i'}} \qquad |
1880 \mbox{for all}~ i \neq i'. |
1884 \mbox{for all}~ i \neq i'. |
1881 \] |
1885 \] |
1882 and they are injective: |
1886 The constructor functions are injective: |
1883 \[ |
1887 \[ |
1884 (C^j@i~x@1~\dots~x@{m^j@i} = C^j@i~y@1~\dots~y@{m^j@i}) = |
1888 (C^j@i~x@1~\dots~x@{m^j@i} = C^j@i~y@1~\dots~y@{m^j@i}) = |
1885 (x@1 = y@1 \land \dots \land x@{m^j@i} = y@{m^j@i}) |
1889 (x@1 = y@1 \land \dots \land x@{m^j@i} = y@{m^j@i}) |
1886 \] |
1890 \] |
1887 Because the number of distinctness inequalities is quadratic in the number of |
1891 Because the number of distinctness inequalities is quadratic in the number of |
1893 Then distinctness of constructor terms is expressed by: |
1897 Then distinctness of constructor terms is expressed by: |
1894 \[ |
1898 \[ |
1895 t@j_ord \, x \neq t@j_ord \, y \Imp x \neq y. |
1899 t@j_ord \, x \neq t@j_ord \, y \Imp x \neq y. |
1896 \] |
1900 \] |
1897 |
1901 |
1898 \medskip The datatype package also provides structural induction rules. For |
1902 \subsubsection{Structural induction} |
|
1903 |
|
1904 The datatype package also provides structural induction rules. For |
1899 datatypes without nested recursion, this is of the following form: |
1905 datatypes without nested recursion, this is of the following form: |
1900 \[ |
1906 \[ |
1901 \infer{P@1~x@1 \wedge \dots \wedge P@n~x@n} |
1907 \infer{P@1~x@1 \wedge \dots \wedge P@n~x@n} |
1902 {\begin{array}{lcl} |
1908 {\begin{array}{lcl} |
1903 \Forall x@1 \dots x@{m^1@1}. |
1909 \Forall x@1 \dots x@{m^1@1}. |
2181 {\out Level 3} |
2187 {\out Level 3} |
2182 {\out ! x. Cons x xs ~= xs} |
2188 {\out ! x. Cons x xs ~= xs} |
2183 {\out No subgoals!} |
2189 {\out No subgoals!} |
2184 \ttbreak |
2190 \ttbreak |
2185 qed_spec_mp "not_Cons_self"; |
2191 qed_spec_mp "not_Cons_self"; |
2186 {\out val not_Cons_self = "Cons x xs ~= xs";} |
2192 {\out val not_Cons_self = "Cons x xs ~= xs" : thm} |
2187 \end{ttbox} |
2193 \end{ttbox} |
2188 Because both subgoals could have been proved by \texttt{Asm_simp_tac} |
2194 Because both subgoals could have been proved by \texttt{Asm_simp_tac} |
2189 we could have done that in one step: |
2195 we could have done that in one step: |
2190 \begin{ttbox} |
2196 \begin{ttbox} |
2191 by (ALLGOALS Asm_simp_tac); |
2197 by (ALLGOALS Asm_simp_tac); |
2264 \index{recursion!primitive|(} |
2270 \index{recursion!primitive|(} |
2265 \index{*primrec|(} |
2271 \index{*primrec|(} |
2266 |
2272 |
2267 Datatypes come with a uniform way of defining functions, {\bf primitive |
2273 Datatypes come with a uniform way of defining functions, {\bf primitive |
2268 recursion}. In principle, one could introduce primitive recursive functions |
2274 recursion}. In principle, one could introduce primitive recursive functions |
2269 by asserting their reduction rules as new axioms. Here is a counter-example |
2275 by asserting their reduction rules as new axioms, but this is not recommended: |
2270 (you should not do such things yourself): |
2276 \begin{ttbox}\slshape |
2271 \begin{ttbox} |
|
2272 Append = Main + |
2277 Append = Main + |
2273 consts app :: ['a list, 'a list] => 'a list |
2278 consts app :: ['a list, 'a list] => 'a list |
2274 rules |
2279 rules |
2275 app_Nil "app [] ys = ys" |
2280 app_Nil "app [] ys = ys" |
2276 app_Cons "app (x#xs) ys = x#app xs ys" |
2281 app_Cons "app (x#xs) ys = x#app xs ys" |
2277 end |
2282 end |
2278 \end{ttbox} |
2283 \end{ttbox} |
2279 But asserting axioms brings the danger of accidentally asserting nonsense, as |
2284 Asserting axioms brings the danger of accidentally asserting nonsense, as |
2280 in \verb$app [] ys = us$. |
2285 in \verb$app [] ys = us$. |
2281 |
2286 |
2282 The \ttindex{primrec} declaration is a safe means of defining primitive |
2287 The \ttindex{primrec} declaration is a safe means of defining primitive |
2283 recursive functions on datatypes: |
2288 recursive functions on datatypes: |
2284 \begin{ttbox} |
2289 \begin{ttbox} |
2309 \dots \, z@n = r \] such that $C$ is a constructor of the datatype, $r$ |
2314 \dots \, z@n = r \] such that $C$ is a constructor of the datatype, $r$ |
2310 contains only the free variables on the left-hand side, and all recursive |
2315 contains only the free variables on the left-hand side, and all recursive |
2311 calls in $r$ are of the form $f \, \dots \, y@i \, \dots$ for some $i$. There |
2316 calls in $r$ are of the form $f \, \dots \, y@i \, \dots$ for some $i$. There |
2312 must be at most one reduction rule for each constructor. The order is |
2317 must be at most one reduction rule for each constructor. The order is |
2313 immaterial. For missing constructors, the function is defined to return a |
2318 immaterial. For missing constructors, the function is defined to return a |
2314 default value. Also note that all reduction rules are added to the default |
2319 default value. |
2315 simpset. |
2320 |
2316 |
|
2317 If you would like to refer to some rule by name, then you must prefix |
2321 If you would like to refer to some rule by name, then you must prefix |
2318 the rule with an identifier. These identifiers, like those in the |
2322 the rule with an identifier. These identifiers, like those in the |
2319 \texttt{rules} section of a theory, will be visible at the \ML\ level. |
2323 \texttt{rules} section of a theory, will be visible at the \ML\ level. |
2320 |
2324 |
2321 The primitive recursive function can have infix or mixfix syntax: |
2325 The primitive recursive function can have infix or mixfix syntax: |
2322 \begin{ttbox}\underscoreon |
2326 \begin{ttbox}\underscoreon |
2323 Append = List + |
|
2324 consts "@" :: ['a list, 'a list] => 'a list (infixr 60) |
2327 consts "@" :: ['a list, 'a list] => 'a list (infixr 60) |
2325 primrec |
2328 primrec |
2326 "[] @ ys = ys" |
2329 "[] @ ys = ys" |
2327 "(x#xs) @ ys = x#(xs @ ys)" |
2330 "(x#xs) @ ys = x#(xs @ ys)" |
2328 end |
2331 \end{ttbox} |
2329 \end{ttbox} |
2332 |
2330 |
2333 The reduction rules become part of the default simpset, which |
2331 The reduction rules for {\tt\at} become part of the default simpset, which |
|
2332 leads to short proof scripts: |
2334 leads to short proof scripts: |
2333 \begin{ttbox}\underscoreon |
2335 \begin{ttbox}\underscoreon |
2334 Goal "(xs @ ys) @ zs = xs @ (ys @ zs)"; |
2336 Goal "(xs @ ys) @ zs = xs @ (ys @ zs)"; |
2335 by (induct\_tac "xs" 1); |
2337 by (induct\_tac "xs" 1); |
2336 by (ALLGOALS Asm\_simp\_tac); |
2338 by (ALLGOALS Asm\_simp\_tac); |