doc-src/Codegen/Thy/Program.thy
author haftmann
Tue, 03 Mar 2009 11:00:51 +0100
changeset 30209 2f4684e2ea95
parent 29735 doc-src/IsarAdvanced/Codegen/Thy/Program.thy@6df726203e39
child 30210 853abb4853cc
permissions -rw-r--r--
more canonical directory structure of manuals
haftmann@28213
     1
theory Program
haftmann@28419
     2
imports Introduction
haftmann@28213
     3
begin
haftmann@28213
     4
haftmann@28419
     5
section {* Turning Theories into Programs \label{sec:program} *}
haftmann@28213
     6
haftmann@28213
     7
subsection {* The @{text "Isabelle/HOL"} default setup *}
haftmann@28213
     8
haftmann@28447
     9
text {*
haftmann@28447
    10
  We have already seen how by default equations stemming from
haftmann@28447
    11
  @{command definition}/@{command primrec}/@{command fun}
haftmann@28447
    12
  statements are used for code generation.  This default behaviour
haftmann@29560
    13
  can be changed, e.g. by providing different code equations.
haftmann@28593
    14
  All kinds of customisation shown in this section is \emph{safe}
haftmann@28447
    15
  in the sense that the user does not have to worry about
haftmann@28447
    16
  correctness -- all programs generatable that way are partially
haftmann@28447
    17
  correct.
haftmann@28447
    18
*}
haftmann@28447
    19
haftmann@28213
    20
subsection {* Selecting code equations *}
haftmann@28213
    21
haftmann@28419
    22
text {*
haftmann@28447
    23
  Coming back to our introductory example, we
haftmann@29560
    24
  could provide an alternative code equations for @{const dequeue}
haftmann@28447
    25
  explicitly:
haftmann@28419
    26
*}
haftmann@28213
    27
haftmann@28564
    28
lemma %quote [code]:
haftmann@29735
    29
  "dequeue (AQueue xs []) =
haftmann@29735
    30
     (if xs = [] then (None, AQueue [] [])
haftmann@29735
    31
       else dequeue (AQueue [] (rev xs)))"
haftmann@29735
    32
  "dequeue (AQueue xs (y # ys)) =
haftmann@29735
    33
     (Some y, AQueue xs ys)"
haftmann@28419
    34
  by (cases xs, simp_all) (cases "rev xs", simp_all)
haftmann@28213
    35
haftmann@28419
    36
text {*
haftmann@28562
    37
  \noindent The annotation @{text "[code]"} is an @{text Isar}
haftmann@28419
    38
  @{text attribute} which states that the given theorems should be
haftmann@29560
    39
  considered as code equations for a @{text fun} statement --
haftmann@28419
    40
  the corresponding constant is determined syntactically.  The resulting code:
haftmann@28419
    41
*}
haftmann@28213
    42
haftmann@28564
    43
text %quote {*@{code_stmts dequeue (consts) dequeue (Haskell)}*}
haftmann@28419
    44
haftmann@28419
    45
text {*
haftmann@28419
    46
  \noindent You may note that the equality test @{term "xs = []"} has been
haftmann@28419
    47
  replaced by the predicate @{term "null xs"}.  This is due to the default
haftmann@28419
    48
  setup in the \qn{preprocessor} to be discussed further below (\secref{sec:preproc}).
haftmann@28419
    49
haftmann@28419
    50
  Changing the default constructor set of datatypes is also
haftmann@29731
    51
  possible.  See \secref{sec:datatypes} for an example.
haftmann@28419
    52
haftmann@28419
    53
  As told in \secref{sec:concept}, code generation is based
haftmann@28419
    54
  on a structured collection of code theorems.
haftmann@28419
    55
  For explorative purpose, this collection
haftmann@28419
    56
  may be inspected using the @{command code_thms} command:
haftmann@28419
    57
*}
haftmann@28419
    58
haftmann@28564
    59
code_thms %quote dequeue
haftmann@28419
    60
haftmann@28419
    61
text {*
haftmann@29560
    62
  \noindent prints a table with \emph{all} code equations
haftmann@28419
    63
  for @{const dequeue}, including
haftmann@29560
    64
  \emph{all} code equations those equations depend
haftmann@28419
    65
  on recursively.
haftmann@28419
    66
  
haftmann@28419
    67
  Similarly, the @{command code_deps} command shows a graph
haftmann@29560
    68
  visualising dependencies between code equations.
haftmann@28419
    69
*}
haftmann@28419
    70
haftmann@28419
    71
subsection {* @{text class} and @{text instantiation} *}
haftmann@28419
    72
haftmann@28419
    73
text {*
haftmann@28447
    74
  Concerning type classes and code generation, let us examine an example
haftmann@28419
    75
  from abstract algebra:
haftmann@28419
    76
*}
haftmann@28419
    77
haftmann@29731
    78
class %quote semigroup =
haftmann@28419
    79
  fixes mult :: "'a \<Rightarrow> 'a \<Rightarrow> 'a" (infixl "\<otimes>" 70)
haftmann@28419
    80
  assumes assoc: "(x \<otimes> y) \<otimes> z = x \<otimes> (y \<otimes> z)"
haftmann@28419
    81
haftmann@28564
    82
class %quote monoid = semigroup +
haftmann@28419
    83
  fixes neutral :: 'a ("\<one>")
haftmann@28419
    84
  assumes neutl: "\<one> \<otimes> x = x"
haftmann@28419
    85
    and neutr: "x \<otimes> \<one> = x"
haftmann@28419
    86
haftmann@28564
    87
instantiation %quote nat :: monoid
haftmann@28419
    88
begin
haftmann@28419
    89
haftmann@28564
    90
primrec %quote mult_nat where
haftmann@28419
    91
    "0 \<otimes> n = (0\<Colon>nat)"
haftmann@28419
    92
  | "Suc m \<otimes> n = n + m \<otimes> n"
haftmann@28419
    93
haftmann@28564
    94
definition %quote neutral_nat where
haftmann@28419
    95
  "\<one> = Suc 0"
haftmann@28419
    96
haftmann@28564
    97
lemma %quote add_mult_distrib:
haftmann@28419
    98
  fixes n m q :: nat
haftmann@28419
    99
  shows "(n + m) \<otimes> q = n \<otimes> q + m \<otimes> q"
haftmann@28419
   100
  by (induct n) simp_all
haftmann@28419
   101
haftmann@28564
   102
instance %quote proof
haftmann@28419
   103
  fix m n q :: nat
haftmann@28419
   104
  show "m \<otimes> n \<otimes> q = m \<otimes> (n \<otimes> q)"
haftmann@28419
   105
    by (induct m) (simp_all add: add_mult_distrib)
haftmann@28419
   106
  show "\<one> \<otimes> n = n"
haftmann@28419
   107
    by (simp add: neutral_nat_def)
haftmann@28419
   108
  show "m \<otimes> \<one> = m"
haftmann@28419
   109
    by (induct m) (simp_all add: neutral_nat_def)
haftmann@28419
   110
qed
haftmann@28419
   111
haftmann@28564
   112
end %quote
haftmann@28419
   113
haftmann@28419
   114
text {*
haftmann@28419
   115
  \noindent We define the natural operation of the natural numbers
haftmann@28419
   116
  on monoids:
haftmann@28419
   117
*}
haftmann@28419
   118
haftmann@28564
   119
primrec %quote (in monoid) pow :: "nat \<Rightarrow> 'a \<Rightarrow> 'a" where
haftmann@28419
   120
    "pow 0 a = \<one>"
haftmann@28419
   121
  | "pow (Suc n) a = a \<otimes> pow n a"
haftmann@28419
   122
haftmann@28419
   123
text {*
haftmann@28419
   124
  \noindent This we use to define the discrete exponentiation function:
haftmann@28419
   125
*}
haftmann@28419
   126
haftmann@28564
   127
definition %quote bexp :: "nat \<Rightarrow> nat" where
haftmann@28419
   128
  "bexp n = pow n (Suc (Suc 0))"
haftmann@28419
   129
haftmann@28419
   130
text {*
haftmann@28419
   131
  \noindent The corresponding code:
haftmann@28419
   132
*}
haftmann@28419
   133
haftmann@28564
   134
text %quote {*@{code_stmts bexp (Haskell)}*}
haftmann@28419
   135
haftmann@28419
   136
text {*
haftmann@28447
   137
  \noindent This is a convenient place to show how explicit dictionary construction
haftmann@28419
   138
  manifests in generated code (here, the same example in @{text SML}):
haftmann@28419
   139
*}
haftmann@28419
   140
haftmann@28564
   141
text %quote {*@{code_stmts bexp (SML)}*}
haftmann@28419
   142
haftmann@28447
   143
text {*
haftmann@28447
   144
  \noindent Note the parameters with trailing underscore (@{verbatim "A_"})
haftmann@28447
   145
    which are the dictionary parameters.
haftmann@28447
   146
*}
haftmann@28419
   147
haftmann@28419
   148
subsection {* The preprocessor \label{sec:preproc} *}
haftmann@28419
   149
haftmann@28419
   150
text {*
haftmann@28419
   151
  Before selected function theorems are turned into abstract
haftmann@28419
   152
  code, a chain of definitional transformation steps is carried
haftmann@28419
   153
  out: \emph{preprocessing}.  In essence, the preprocessor
haftmann@28419
   154
  consists of two components: a \emph{simpset} and \emph{function transformers}.
haftmann@28419
   155
haftmann@28419
   156
  The \emph{simpset} allows to employ the full generality of the Isabelle
haftmann@28419
   157
  simplifier.  Due to the interpretation of theorems
haftmann@29560
   158
  as code equations, rewrites are applied to the right
haftmann@28419
   159
  hand side and the arguments of the left hand side of an
haftmann@28419
   160
  equation, but never to the constant heading the left hand side.
haftmann@28419
   161
  An important special case are \emph{inline theorems} which may be
haftmann@28419
   162
  declared and undeclared using the
haftmann@28419
   163
  \emph{code inline} or \emph{code inline del} attribute respectively.
haftmann@28419
   164
haftmann@28419
   165
  Some common applications:
haftmann@28419
   166
*}
haftmann@28419
   167
haftmann@28419
   168
text_raw {*
haftmann@28419
   169
  \begin{itemize}
haftmann@28419
   170
*}
haftmann@28419
   171
haftmann@28419
   172
text {*
haftmann@28419
   173
     \item replacing non-executable constructs by executable ones:
haftmann@28419
   174
*}     
haftmann@28419
   175
haftmann@28564
   176
lemma %quote [code inline]:
haftmann@28419
   177
  "x \<in> set xs \<longleftrightarrow> x mem xs" by (induct xs) simp_all
haftmann@28419
   178
haftmann@28419
   179
text {*
haftmann@28419
   180
     \item eliminating superfluous constants:
haftmann@28419
   181
*}
haftmann@28419
   182
haftmann@28564
   183
lemma %quote [code inline]:
haftmann@28419
   184
  "1 = Suc 0" by simp
haftmann@28419
   185
haftmann@28419
   186
text {*
haftmann@28419
   187
     \item replacing executable but inconvenient constructs:
haftmann@28419
   188
*}
haftmann@28419
   189
haftmann@28564
   190
lemma %quote [code inline]:
haftmann@28419
   191
  "xs = [] \<longleftrightarrow> List.null xs" by (induct xs) simp_all
haftmann@28419
   192
haftmann@28419
   193
text_raw {*
haftmann@28419
   194
  \end{itemize}
haftmann@28419
   195
*}
haftmann@28419
   196
haftmann@28419
   197
text {*
haftmann@28447
   198
  \noindent \emph{Function transformers} provide a very general interface,
haftmann@28419
   199
  transforming a list of function theorems to another
haftmann@28419
   200
  list of function theorems, provided that neither the heading
haftmann@28419
   201
  constant nor its type change.  The @{term "0\<Colon>nat"} / @{const Suc}
haftmann@28419
   202
  pattern elimination implemented in
haftmann@28419
   203
  theory @{text Efficient_Nat} (see \secref{eff_nat}) uses this
haftmann@28419
   204
  interface.
haftmann@28419
   205
haftmann@28419
   206
  \noindent The current setup of the preprocessor may be inspected using
haftmann@28419
   207
  the @{command print_codesetup} command.
haftmann@28419
   208
  @{command code_thms} provides a convenient
haftmann@28419
   209
  mechanism to inspect the impact of a preprocessor setup
haftmann@29560
   210
  on code equations.
haftmann@28419
   211
haftmann@28419
   212
  \begin{warn}
haftmann@28419
   213
    The attribute \emph{code unfold}
haftmann@28447
   214
    associated with the @{text "SML code generator"} also applies to
haftmann@28447
   215
    the @{text "generic code generator"}:
haftmann@28447
   216
    \emph{code unfold} implies \emph{code inline}.
haftmann@28419
   217
  \end{warn}
haftmann@28419
   218
*}
haftmann@28419
   219
haftmann@28419
   220
subsection {* Datatypes \label{sec:datatypes} *}
haftmann@28419
   221
haftmann@28419
   222
text {*
haftmann@28419
   223
  Conceptually, any datatype is spanned by a set of
haftmann@29731
   224
  \emph{constructors} of type @{text "\<tau> = \<dots> \<Rightarrow> \<kappa> \<alpha>\<^isub>1 \<dots> \<alpha>\<^isub>n"} where @{text
haftmann@29731
   225
  "{\<alpha>\<^isub>1, \<dots>, \<alpha>\<^isub>n}"} is exactly the set of \emph{all} type variables in
haftmann@29731
   226
  @{text "\<tau>"}.  The HOL datatype package by default registers any new
haftmann@29731
   227
  datatype in the table of datatypes, which may be inspected using the
haftmann@29731
   228
  @{command print_codesetup} command.
haftmann@28419
   229
haftmann@29731
   230
  In some cases, it is appropriate to alter or extend this table.  As
haftmann@29731
   231
  an example, we will develop an alternative representation of the
haftmann@29731
   232
  queue example given in \secref{sec:intro}.  The amortised
haftmann@29731
   233
  representation is convenient for generating code but exposes its
haftmann@29731
   234
  \qt{implementation} details, which may be cumbersome when proving
haftmann@29731
   235
  theorems about it.  Therefore, here a simple, straightforward
haftmann@29731
   236
  representation of queues:
haftmann@28419
   237
*}
haftmann@28419
   238
haftmann@29731
   239
datatype %quote 'a queue = Queue "'a list"
haftmann@28419
   240
haftmann@29731
   241
definition %quote empty :: "'a queue" where
haftmann@29731
   242
  "empty = Queue []"
haftmann@29731
   243
haftmann@29731
   244
primrec %quote enqueue :: "'a \<Rightarrow> 'a queue \<Rightarrow> 'a queue" where
haftmann@29731
   245
  "enqueue x (Queue xs) = Queue (xs @ [x])"
haftmann@29731
   246
haftmann@29731
   247
fun %quote dequeue :: "'a queue \<Rightarrow> 'a option \<times> 'a queue" where
haftmann@29731
   248
    "dequeue (Queue []) = (None, Queue [])"
haftmann@29731
   249
  | "dequeue (Queue (x # xs)) = (Some x, Queue xs)"
haftmann@28419
   250
haftmann@28419
   251
text {*
haftmann@29731
   252
  \noindent This we can use directly for proving;  for executing,
haftmann@29731
   253
  we provide an alternative characterisation:
haftmann@28419
   254
*}
haftmann@28419
   255
haftmann@29731
   256
definition %quote AQueue :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a queue" where
haftmann@29731
   257
  "AQueue xs ys = Queue (ys @ rev xs)"
haftmann@29731
   258
haftmann@29731
   259
code_datatype %quote AQueue
haftmann@29731
   260
haftmann@29735
   261
text {*
haftmann@29735
   262
  \noindent Here we define a \qt{constructor} @{const "AQueue"} which
haftmann@29735
   263
  is defined in terms of @{text "Queue"} and interprets its arguments
haftmann@29735
   264
  according to what the \emph{content} of an amortised queue is supposed
haftmann@29735
   265
  to be.  Equipped with this, we are able to prove the following equations
haftmann@29735
   266
  for our primitive queue operations which \qt{implement} the simple
haftmann@29735
   267
  queues in an amortised fashion:
haftmann@29735
   268
*}
haftmann@29731
   269
haftmann@29731
   270
lemma %quote empty_AQueue [code]:
haftmann@29731
   271
  "empty = AQueue [] []"
haftmann@29731
   272
  unfolding AQueue_def empty_def by simp
haftmann@29731
   273
haftmann@29731
   274
lemma %quote enqueue_AQueue [code]:
haftmann@29731
   275
  "enqueue x (AQueue xs ys) = AQueue (x # xs) ys"
haftmann@29731
   276
  unfolding AQueue_def by simp
haftmann@29731
   277
haftmann@29731
   278
lemma %quote dequeue_AQueue [code]:
haftmann@29731
   279
  "dequeue (AQueue xs []) =
haftmann@29735
   280
    (if xs = [] then (None, AQueue [] [])
haftmann@29735
   281
    else dequeue (AQueue [] (rev xs)))"
haftmann@29731
   282
  "dequeue (AQueue xs (y # ys)) = (Some y, AQueue xs ys)"
haftmann@29731
   283
  unfolding AQueue_def by simp_all
haftmann@29731
   284
haftmann@29735
   285
text {*
haftmann@29735
   286
  \noindent For completeness, we provide a substitute for the
haftmann@29735
   287
  @{text case} combinator on queues:
haftmann@29735
   288
*}
haftmann@29731
   289
haftmann@29735
   290
definition %quote
haftmann@29735
   291
  aqueue_case_def: "aqueue_case = queue_case"
haftmann@29731
   292
haftmann@29735
   293
lemma %quote aqueue_case [code, code inline]:
haftmann@29735
   294
  "queue_case = aqueue_case"
haftmann@29735
   295
  unfolding aqueue_case_def ..
haftmann@29731
   296
haftmann@29735
   297
lemma %quote case_AQueue [code]:
haftmann@29731
   298
  "aqueue_case f (AQueue xs ys) = f (ys @ rev xs)"
haftmann@29735
   299
  unfolding aqueue_case_def AQueue_def by simp
haftmann@29731
   300
haftmann@29735
   301
text {*
haftmann@29735
   302
  \noindent The resulting code looks as expected:
haftmann@29735
   303
*}
haftmann@29731
   304
haftmann@29731
   305
text %quote {*@{code_stmts empty enqueue dequeue (SML)}*}
haftmann@28419
   306
haftmann@28419
   307
text {*
haftmann@29731
   308
  \noindent From this example, it can be glimpsed that using own
haftmann@29731
   309
  constructor sets is a little delicate since it changes the set of
haftmann@29731
   310
  valid patterns for values of that type.  Without going into much
haftmann@29731
   311
  detail, here some practical hints:
haftmann@28419
   312
haftmann@28419
   313
  \begin{itemize}
haftmann@29731
   314
haftmann@29731
   315
    \item When changing the constructor set for datatypes, take care
haftmann@29731
   316
      to provide an alternative for the @{text case} combinator
haftmann@29731
   317
      (e.g.~by replacing it using the preprocessor).
haftmann@29731
   318
haftmann@29731
   319
    \item Values in the target language need not to be normalised --
haftmann@29731
   320
      different values in the target language may represent the same
haftmann@29731
   321
      value in the logic.
haftmann@29731
   322
haftmann@29731
   323
    \item Usually, a good methodology to deal with the subtleties of
haftmann@29731
   324
      pattern matching is to see the type as an abstract type: provide
haftmann@29731
   325
      a set of operations which operate on the concrete representation
haftmann@29731
   326
      of the type, and derive further operations by combinations of
haftmann@29731
   327
      these primitive ones, without relying on a particular
haftmann@29731
   328
      representation.
haftmann@29731
   329
haftmann@28419
   330
  \end{itemize}
haftmann@28419
   331
*}
haftmann@28419
   332
haftmann@28213
   333
haftmann@28213
   334
subsection {* Equality and wellsortedness *}
haftmann@28213
   335
haftmann@28419
   336
text {*
haftmann@28419
   337
  Surely you have already noticed how equality is treated
haftmann@28419
   338
  by the code generator:
haftmann@28419
   339
*}
haftmann@28419
   340
haftmann@28564
   341
primrec %quote collect_duplicates :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a list \<Rightarrow> 'a list" where
haftmann@28447
   342
  "collect_duplicates xs ys [] = xs"
haftmann@28419
   343
  | "collect_duplicates xs ys (z#zs) = (if z \<in> set xs
haftmann@28419
   344
      then if z \<in> set ys
haftmann@28419
   345
        then collect_duplicates xs ys zs
haftmann@28419
   346
        else collect_duplicates xs (z#ys) zs
haftmann@28419
   347
      else collect_duplicates (z#xs) (z#ys) zs)"
haftmann@28419
   348
haftmann@28419
   349
text {*
haftmann@28428
   350
  \noindent The membership test during preprocessing is rewritten,
haftmann@28419
   351
  resulting in @{const List.member}, which itself
haftmann@28419
   352
  performs an explicit equality check.
haftmann@28419
   353
*}
haftmann@28419
   354
haftmann@28564
   355
text %quote {*@{code_stmts collect_duplicates (SML)}*}
haftmann@28419
   356
haftmann@28419
   357
text {*
haftmann@28419
   358
  \noindent Obviously, polymorphic equality is implemented the Haskell
haftmann@28419
   359
  way using a type class.  How is this achieved?  HOL introduces
haftmann@28419
   360
  an explicit class @{class eq} with a corresponding operation
haftmann@28419
   361
  @{const eq_class.eq} such that @{thm eq [no_vars]}.
haftmann@28447
   362
  The preprocessing framework does the rest by propagating the
haftmann@29560
   363
  @{class eq} constraints through all dependent code equations.
haftmann@28419
   364
  For datatypes, instances of @{class eq} are implicitly derived
haftmann@28419
   365
  when possible.  For other types, you may instantiate @{text eq}
haftmann@28419
   366
  manually like any other type class.
haftmann@28419
   367
haftmann@28419
   368
  Though this @{text eq} class is designed to get rarely in
haftmann@28419
   369
  the way, a subtlety
haftmann@28419
   370
  enters the stage when definitions of overloaded constants
haftmann@28419
   371
  are dependent on operational equality.  For example, let
haftmann@28447
   372
  us define a lexicographic ordering on tuples
haftmann@28447
   373
  (also see theory @{theory Product_ord}):
haftmann@28419
   374
*}
haftmann@28419
   375
haftmann@28564
   376
instantiation %quote "*" :: (order, order) order
haftmann@28419
   377
begin
haftmann@28419
   378
haftmann@28564
   379
definition %quote [code del]:
haftmann@28447
   380
  "x \<le> y \<longleftrightarrow> fst x < fst y \<or> fst x = fst y \<and> snd x \<le> snd y"
haftmann@28419
   381
haftmann@28564
   382
definition %quote [code del]:
haftmann@28447
   383
  "x < y \<longleftrightarrow> fst x < fst y \<or> fst x = fst y \<and> snd x < snd y"
haftmann@28419
   384
haftmann@28564
   385
instance %quote proof
haftmann@28447
   386
qed (auto simp: less_eq_prod_def less_prod_def intro: order_less_trans)
haftmann@28419
   387
haftmann@28564
   388
end %quote
haftmann@28419
   389
haftmann@28564
   390
lemma %quote order_prod [code]:
haftmann@28447
   391
  "(x1 \<Colon> 'a\<Colon>order, y1 \<Colon> 'b\<Colon>order) < (x2, y2) \<longleftrightarrow>
haftmann@28447
   392
     x1 < x2 \<or> x1 = x2 \<and> y1 < y2"
haftmann@28447
   393
  "(x1 \<Colon> 'a\<Colon>order, y1 \<Colon> 'b\<Colon>order) \<le> (x2, y2) \<longleftrightarrow>
haftmann@28447
   394
     x1 < x2 \<or> x1 = x2 \<and> y1 \<le> y2"
haftmann@28447
   395
  by (simp_all add: less_prod_def less_eq_prod_def)
haftmann@28419
   396
haftmann@28419
   397
text {*
haftmann@28428
   398
  \noindent Then code generation will fail.  Why?  The definition
haftmann@28419
   399
  of @{term "op \<le>"} depends on equality on both arguments,
haftmann@28419
   400
  which are polymorphic and impose an additional @{class eq}
haftmann@28447
   401
  class constraint, which the preprocessor does not propagate
haftmann@28447
   402
  (for technical reasons).
haftmann@28419
   403
haftmann@28419
   404
  The solution is to add @{class eq} explicitly to the first sort arguments in the
haftmann@28419
   405
  code theorems:
haftmann@28419
   406
*}
haftmann@28419
   407
haftmann@28564
   408
lemma %quote order_prod_code [code]:
haftmann@28447
   409
  "(x1 \<Colon> 'a\<Colon>{order, eq}, y1 \<Colon> 'b\<Colon>order) < (x2, y2) \<longleftrightarrow>
haftmann@28447
   410
     x1 < x2 \<or> x1 = x2 \<and> y1 < y2"
haftmann@28447
   411
  "(x1 \<Colon> 'a\<Colon>{order, eq}, y1 \<Colon> 'b\<Colon>order) \<le> (x2, y2) \<longleftrightarrow>
haftmann@28447
   412
     x1 < x2 \<or> x1 = x2 \<and> y1 \<le> y2"
haftmann@28447
   413
  by (simp_all add: less_prod_def less_eq_prod_def)
haftmann@28419
   414
haftmann@28419
   415
text {*
haftmann@28419
   416
  \noindent Then code generation succeeds:
haftmann@28419
   417
*}
haftmann@28419
   418
haftmann@28564
   419
text %quote {*@{code_stmts "op \<le> \<Colon> _ \<times> _ \<Rightarrow> _ \<times> _ \<Rightarrow> bool" (SML)}*}
haftmann@28419
   420
haftmann@28419
   421
text {*
haftmann@29560
   422
  In some cases, the automatically derived code equations
haftmann@28419
   423
  for equality on a particular type may not be appropriate.
haftmann@28419
   424
  As example, watch the following datatype representing
haftmann@28419
   425
  monomorphic parametric types (where type constructors
haftmann@28419
   426
  are referred to by natural numbers):
haftmann@28419
   427
*}
haftmann@28419
   428
haftmann@28564
   429
datatype %quote monotype = Mono nat "monotype list"
haftmann@28419
   430
(*<*)
haftmann@28419
   431
lemma monotype_eq:
haftmann@28462
   432
  "eq_class.eq (Mono tyco1 typargs1) (Mono tyco2 typargs2) \<equiv> 
haftmann@28462
   433
     eq_class.eq tyco1 tyco2 \<and> eq_class.eq typargs1 typargs2" by (simp add: eq)
haftmann@28419
   434
(*>*)
haftmann@28419
   435
haftmann@28419
   436
text {*
haftmann@28462
   437
  \noindent Then code generation for SML would fail with a message
haftmann@28419
   438
  that the generated code contains illegal mutual dependencies:
haftmann@28419
   439
  the theorem @{thm monotype_eq [no_vars]} already requires the
haftmann@28419
   440
  instance @{text "monotype \<Colon> eq"}, which itself requires
haftmann@28419
   441
  @{thm monotype_eq [no_vars]};  Haskell has no problem with mutually
haftmann@28462
   442
  recursive @{text instance} and @{text function} definitions,
haftmann@28593
   443
  but the SML serialiser does not support this.
haftmann@28419
   444
haftmann@28447
   445
  In such cases, you have to provide your own equality equations
haftmann@28419
   446
  involving auxiliary constants.  In our case,
haftmann@28419
   447
  @{const [show_types] list_all2} can do the job:
haftmann@28419
   448
*}
haftmann@28419
   449
haftmann@28564
   450
lemma %quote monotype_eq_list_all2 [code]:
haftmann@28419
   451
  "eq_class.eq (Mono tyco1 typargs1) (Mono tyco2 typargs2) \<longleftrightarrow>
haftmann@28462
   452
     eq_class.eq tyco1 tyco2 \<and> list_all2 eq_class.eq typargs1 typargs2"
haftmann@28419
   453
  by (simp add: eq list_all2_eq [symmetric])
haftmann@28419
   454
haftmann@28419
   455
text {*
haftmann@28419
   456
  \noindent does not depend on instance @{text "monotype \<Colon> eq"}:
haftmann@28419
   457
*}
haftmann@28419
   458
haftmann@28564
   459
text %quote {*@{code_stmts "eq_class.eq :: monotype \<Rightarrow> monotype \<Rightarrow> bool" (SML)}*}
haftmann@28419
   460
haftmann@28419
   461
haftmann@28462
   462
subsection {* Explicit partiality *}
haftmann@28213
   463
haftmann@28462
   464
text {*
haftmann@28462
   465
  Partiality usually enters the game by partial patterns, as
haftmann@28462
   466
  in the following example, again for amortised queues:
haftmann@28462
   467
*}
haftmann@28462
   468
haftmann@29735
   469
definition %quote strict_dequeue :: "'a queue \<Rightarrow> 'a \<times> 'a queue" where
haftmann@29735
   470
  "strict_dequeue q = (case dequeue q
haftmann@29735
   471
    of (Some x, q') \<Rightarrow> (x, q'))"
haftmann@29735
   472
haftmann@29735
   473
lemma %quote strict_dequeue_AQueue [code]:
haftmann@29735
   474
  "strict_dequeue (AQueue xs (y # ys)) = (y, AQueue xs ys)"
haftmann@29735
   475
  "strict_dequeue (AQueue xs []) =
haftmann@29735
   476
    (case rev xs of y # ys \<Rightarrow> (y, AQueue [] ys))"
haftmann@29735
   477
  by (simp_all add: strict_dequeue_def dequeue_AQueue split: list.splits)
haftmann@28462
   478
haftmann@28462
   479
text {*
haftmann@28462
   480
  \noindent In the corresponding code, there is no equation
haftmann@29735
   481
  for the pattern @{term "AQueue [] []"}:
haftmann@28462
   482
*}
haftmann@28462
   483
haftmann@28564
   484
text %quote {*@{code_stmts strict_dequeue (consts) strict_dequeue (Haskell)}*}
haftmann@28462
   485
haftmann@28462
   486
text {*
haftmann@28462
   487
  \noindent In some cases it is desirable to have this
haftmann@28462
   488
  pseudo-\qt{partiality} more explicitly, e.g.~as follows:
haftmann@28462
   489
*}
haftmann@28462
   490
haftmann@28564
   491
axiomatization %quote empty_queue :: 'a
haftmann@28462
   492
haftmann@29735
   493
definition %quote strict_dequeue' :: "'a queue \<Rightarrow> 'a \<times> 'a queue" where
haftmann@29735
   494
  "strict_dequeue' q = (case dequeue q of (Some x, q') \<Rightarrow> (x, q') | _ \<Rightarrow> empty_queue)"
haftmann@28462
   495
haftmann@29735
   496
lemma %quote strict_dequeue'_AQueue [code]:
haftmann@29735
   497
  "strict_dequeue' (AQueue xs []) = (if xs = [] then empty_queue
haftmann@29735
   498
     else strict_dequeue' (AQueue [] (rev xs)))"
haftmann@29735
   499
  "strict_dequeue' (AQueue xs (y # ys)) =
haftmann@29735
   500
     (y, AQueue xs ys)"
haftmann@29735
   501
  by (simp_all add: strict_dequeue'_def dequeue_AQueue split: list.splits)
haftmann@28462
   502
haftmann@28462
   503
text {*
haftmann@29735
   504
  Observe that on the right hand side of the definition of @{const
haftmann@29735
   505
  "strict_dequeue'"} the constant @{const empty_queue} occurs
haftmann@29735
   506
  which is unspecified.
haftmann@28462
   507
haftmann@29735
   508
  Normally, if constants without any code equations occur in a
haftmann@29735
   509
  program, the code generator complains (since in most cases this is
haftmann@29735
   510
  not what the user expects).  But such constants can also be thought
haftmann@29735
   511
  of as function definitions with no equations which always fail,
haftmann@29735
   512
  since there is never a successful pattern match on the left hand
haftmann@29735
   513
  side.  In order to categorise a constant into that category
haftmann@29735
   514
  explicitly, use @{command "code_abort"}:
haftmann@28462
   515
*}
haftmann@28462
   516
haftmann@28564
   517
code_abort %quote empty_queue
haftmann@28462
   518
haftmann@28462
   519
text {*
haftmann@28462
   520
  \noindent Then the code generator will just insert an error or
haftmann@28462
   521
  exception at the appropriate position:
haftmann@28462
   522
*}
haftmann@28462
   523
haftmann@28564
   524
text %quote {*@{code_stmts strict_dequeue' (consts) empty_queue strict_dequeue' (Haskell)}*}
haftmann@28462
   525
haftmann@28462
   526
text {*
haftmann@28462
   527
  \noindent This feature however is rarely needed in practice.
haftmann@28462
   528
  Note also that the @{text HOL} default setup already declares
haftmann@28462
   529
  @{const undefined} as @{command "code_abort"}, which is most
haftmann@28462
   530
  likely to be used in such situations.
haftmann@28462
   531
*}
haftmann@28213
   532
haftmann@28213
   533
end
haftmann@28462
   534