doc-src/IsarAdvanced/Codegen/Thy/Program.thy
changeset 29798 6df726203e39
parent 29796 a342da8ddf39
equal deleted inserted replaced
29797:08ef36ed2f8a 29798:6df726203e39
    24   could provide an alternative code equations for @{const dequeue}
    24   could provide an alternative code equations for @{const dequeue}
    25   explicitly:
    25   explicitly:
    26 *}
    26 *}
    27 
    27 
    28 lemma %quote [code]:
    28 lemma %quote [code]:
    29   "dequeue (Queue xs []) =
    29   "dequeue (AQueue xs []) =
    30      (if xs = [] then (None, Queue [] [])
    30      (if xs = [] then (None, AQueue [] [])
    31        else dequeue (Queue [] (rev xs)))"
    31        else dequeue (AQueue [] (rev xs)))"
    32   "dequeue (Queue xs (y # ys)) =
    32   "dequeue (AQueue xs (y # ys)) =
    33      (Some y, Queue xs ys)"
    33      (Some y, AQueue xs ys)"
    34   by (cases xs, simp_all) (cases "rev xs", simp_all)
    34   by (cases xs, simp_all) (cases "rev xs", simp_all)
    35 
    35 
    36 text {*
    36 text {*
    37   \noindent The annotation @{text "[code]"} is an @{text Isar}
    37   \noindent The annotation @{text "[code]"} is an @{text Isar}
    38   @{text attribute} which states that the given theorems should be
    38   @{text attribute} which states that the given theorems should be
   256 definition %quote AQueue :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a queue" where
   256 definition %quote AQueue :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a queue" where
   257   "AQueue xs ys = Queue (ys @ rev xs)"
   257   "AQueue xs ys = Queue (ys @ rev xs)"
   258 
   258 
   259 code_datatype %quote AQueue
   259 code_datatype %quote AQueue
   260 
   260 
   261 text {* *}
   261 text {*
       
   262   \noindent Here we define a \qt{constructor} @{const "AQueue"} which
       
   263   is defined in terms of @{text "Queue"} and interprets its arguments
       
   264   according to what the \emph{content} of an amortised queue is supposed
       
   265   to be.  Equipped with this, we are able to prove the following equations
       
   266   for our primitive queue operations which \qt{implement} the simple
       
   267   queues in an amortised fashion:
       
   268 *}
   262 
   269 
   263 lemma %quote empty_AQueue [code]:
   270 lemma %quote empty_AQueue [code]:
   264   "empty = AQueue [] []"
   271   "empty = AQueue [] []"
   265   unfolding AQueue_def empty_def by simp
   272   unfolding AQueue_def empty_def by simp
   266 
   273 
   268   "enqueue x (AQueue xs ys) = AQueue (x # xs) ys"
   275   "enqueue x (AQueue xs ys) = AQueue (x # xs) ys"
   269   unfolding AQueue_def by simp
   276   unfolding AQueue_def by simp
   270 
   277 
   271 lemma %quote dequeue_AQueue [code]:
   278 lemma %quote dequeue_AQueue [code]:
   272   "dequeue (AQueue xs []) =
   279   "dequeue (AQueue xs []) =
   273     (if xs = [] then (None, AQueue [] []) else dequeue (AQueue [] (rev xs)))"
   280     (if xs = [] then (None, AQueue [] [])
       
   281     else dequeue (AQueue [] (rev xs)))"
   274   "dequeue (AQueue xs (y # ys)) = (Some y, AQueue xs ys)"
   282   "dequeue (AQueue xs (y # ys)) = (Some y, AQueue xs ys)"
   275   unfolding AQueue_def by simp_all
   283   unfolding AQueue_def by simp_all
   276 
   284 
   277 text {* *}
   285 text {*
   278 
   286   \noindent For completeness, we provide a substitute for the
   279 definition %quote aqueue_case [code inline]:
   287   @{text case} combinator on queues:
   280   "aqueue_case = queue_case"
   288 *}
   281 
   289 
   282 lemma %quote case_AQueue1 [code]:
   290 definition %quote
   283   "queue_case f (AQueue xs ys) = f (ys @ rev xs)"
   291   aqueue_case_def: "aqueue_case = queue_case"
   284   unfolding AQueue_def by simp
   292 
   285 
   293 lemma %quote aqueue_case [code, code inline]:
   286 lemma %quote case_AQueue2 [code]:
   294   "queue_case = aqueue_case"
       
   295   unfolding aqueue_case_def ..
       
   296 
       
   297 lemma %quote case_AQueue [code]:
   287   "aqueue_case f (AQueue xs ys) = f (ys @ rev xs)"
   298   "aqueue_case f (AQueue xs ys) = f (ys @ rev xs)"
   288   unfolding aqueue_case case_AQueue1 ..
   299   unfolding aqueue_case_def AQueue_def by simp
   289 
   300 
   290 text {* *}
   301 text {*
       
   302   \noindent The resulting code looks as expected:
       
   303 *}
   291 
   304 
   292 text %quote {*@{code_stmts empty enqueue dequeue (SML)}*}
   305 text %quote {*@{code_stmts empty enqueue dequeue (SML)}*}
   293 
   306 
   294 text {*
   307 text {*
   295   \noindent From this example, it can be glimpsed that using own
   308   \noindent From this example, it can be glimpsed that using own
   451 text {*
   464 text {*
   452   Partiality usually enters the game by partial patterns, as
   465   Partiality usually enters the game by partial patterns, as
   453   in the following example, again for amortised queues:
   466   in the following example, again for amortised queues:
   454 *}
   467 *}
   455 
   468 
   456 fun %quote strict_dequeue :: "'a Introduction.queue \<Rightarrow> 'a \<times> 'a Introduction.queue" where
   469 definition %quote strict_dequeue :: "'a queue \<Rightarrow> 'a \<times> 'a queue" where
   457   "strict_dequeue (Introduction.Queue xs (y # ys)) = (y, Introduction.Queue xs ys)"
   470   "strict_dequeue q = (case dequeue q
   458   | "strict_dequeue (Introduction.Queue xs []) =
   471     of (Some x, q') \<Rightarrow> (x, q'))"
   459       (case rev xs of y # ys \<Rightarrow> (y, Introduction.Queue [] ys))"
   472 
       
   473 lemma %quote strict_dequeue_AQueue [code]:
       
   474   "strict_dequeue (AQueue xs (y # ys)) = (y, AQueue xs ys)"
       
   475   "strict_dequeue (AQueue xs []) =
       
   476     (case rev xs of y # ys \<Rightarrow> (y, AQueue [] ys))"
       
   477   by (simp_all add: strict_dequeue_def dequeue_AQueue split: list.splits)
   460 
   478 
   461 text {*
   479 text {*
   462   \noindent In the corresponding code, there is no equation
   480   \noindent In the corresponding code, there is no equation
   463   for the pattern @{term "Introduction.Queue [] []"}:
   481   for the pattern @{term "AQueue [] []"}:
   464 *}
   482 *}
   465 
   483 
   466 text %quote {*@{code_stmts strict_dequeue (consts) strict_dequeue (Haskell)}*}
   484 text %quote {*@{code_stmts strict_dequeue (consts) strict_dequeue (Haskell)}*}
   467 
   485 
   468 text {*
   486 text {*
   470   pseudo-\qt{partiality} more explicitly, e.g.~as follows:
   488   pseudo-\qt{partiality} more explicitly, e.g.~as follows:
   471 *}
   489 *}
   472 
   490 
   473 axiomatization %quote empty_queue :: 'a
   491 axiomatization %quote empty_queue :: 'a
   474 
   492 
   475 function %quote strict_dequeue' :: "'a Introduction.queue \<Rightarrow> 'a \<times> 'a Introduction.queue" where
   493 definition %quote strict_dequeue' :: "'a queue \<Rightarrow> 'a \<times> 'a queue" where
   476   "strict_dequeue' (Introduction.Queue xs []) = (if xs = [] then empty_queue
   494   "strict_dequeue' q = (case dequeue q of (Some x, q') \<Rightarrow> (x, q') | _ \<Rightarrow> empty_queue)"
   477      else strict_dequeue' (Introduction.Queue [] (rev xs)))"
   495 
   478   | "strict_dequeue' (Introduction.Queue xs (y # ys)) =
   496 lemma %quote strict_dequeue'_AQueue [code]:
   479        (y, Introduction.Queue xs ys)"
   497   "strict_dequeue' (AQueue xs []) = (if xs = [] then empty_queue
   480 by pat_completeness auto
   498      else strict_dequeue' (AQueue [] (rev xs)))"
   481 
   499   "strict_dequeue' (AQueue xs (y # ys)) =
   482 termination %quote strict_dequeue'
   500      (y, AQueue xs ys)"
   483 by (relation "measure (\<lambda>q::'a Introduction.queue. case q of Introduction.Queue xs ys \<Rightarrow> length xs)") simp_all
   501   by (simp_all add: strict_dequeue'_def dequeue_AQueue split: list.splits)
   484 
   502 
   485 text {*
   503 text {*
   486   \noindent For technical reasons the definition of
   504   Observe that on the right hand side of the definition of @{const
   487   @{const strict_dequeue'} is more involved since it requires
   505   "strict_dequeue'"} the constant @{const empty_queue} occurs
   488   a manual termination proof.  Apart from that observe that
   506   which is unspecified.
   489   on the right hand side of its first equation the constant
   507 
   490   @{const empty_queue} occurs which is unspecified.
   508   Normally, if constants without any code equations occur in a
   491 
   509   program, the code generator complains (since in most cases this is
   492   Normally, if constants without any code equations occur in
   510   not what the user expects).  But such constants can also be thought
   493   a program, the code generator complains (since in most cases
   511   of as function definitions with no equations which always fail,
   494   this is not what the user expects).  But such constants can also
   512   since there is never a successful pattern match on the left hand
   495   be thought of as function definitions with no equations which
   513   side.  In order to categorise a constant into that category
   496   always fail, since there is never a successful pattern match
   514   explicitly, use @{command "code_abort"}:
   497   on the left hand side.  In order to categorise a constant into
       
   498   that category explicitly, use @{command "code_abort"}:
       
   499 *}
   515 *}
   500 
   516 
   501 code_abort %quote empty_queue
   517 code_abort %quote empty_queue
   502 
   518 
   503 text {*
   519 text {*