doc-src/IsarAdvanced/Codegen/Thy/Program.thy
changeset 28462 6ec603695aaf
parent 28456 7a558c872104
child 28562 4e74209f113e
equal deleted inserted replaced
28461:640b7f8f9cad 28462:6ec603695aaf
   418 *}
   418 *}
   419 
   419 
   420 datatype %quoteme monotype = Mono nat "monotype list"
   420 datatype %quoteme monotype = Mono nat "monotype list"
   421 (*<*)
   421 (*<*)
   422 lemma monotype_eq:
   422 lemma monotype_eq:
   423   "Mono tyco1 typargs1 = Mono tyco2 typargs2 \<equiv> 
   423   "eq_class.eq (Mono tyco1 typargs1) (Mono tyco2 typargs2) \<equiv> 
   424      tyco1 = tyco2 \<and> typargs1 = typargs2" by simp
   424      eq_class.eq tyco1 tyco2 \<and> eq_class.eq typargs1 typargs2" by (simp add: eq)
   425 (*>*)
   425 (*>*)
   426 
   426 
   427 text {*
   427 text {*
   428   Then code generation for SML would fail with a message
   428   \noindent Then code generation for SML would fail with a message
   429   that the generated code contains illegal mutual dependencies:
   429   that the generated code contains illegal mutual dependencies:
   430   the theorem @{thm monotype_eq [no_vars]} already requires the
   430   the theorem @{thm monotype_eq [no_vars]} already requires the
   431   instance @{text "monotype \<Colon> eq"}, which itself requires
   431   instance @{text "monotype \<Colon> eq"}, which itself requires
   432   @{thm monotype_eq [no_vars]};  Haskell has no problem with mutually
   432   @{thm monotype_eq [no_vars]};  Haskell has no problem with mutually
   433   recursive @{text inst} and @{text fun} definitions,
   433   recursive @{text instance} and @{text function} definitions,
   434   but the SML serializer does not support this.
   434   but the SML serializer does not support this.
   435 
   435 
   436   In such cases, you have to provide your own equality equations
   436   In such cases, you have to provide your own equality equations
   437   involving auxiliary constants.  In our case,
   437   involving auxiliary constants.  In our case,
   438   @{const [show_types] list_all2} can do the job:
   438   @{const [show_types] list_all2} can do the job:
   439 *}
   439 *}
   440 
   440 
   441 lemma %quoteme monotype_eq_list_all2 [code func]:
   441 lemma %quoteme monotype_eq_list_all2 [code func]:
   442   "eq_class.eq (Mono tyco1 typargs1) (Mono tyco2 typargs2) \<longleftrightarrow>
   442   "eq_class.eq (Mono tyco1 typargs1) (Mono tyco2 typargs2) \<longleftrightarrow>
   443      tyco1 = tyco2 \<and> list_all2 eq_class.eq typargs1 typargs2"
   443      eq_class.eq tyco1 tyco2 \<and> list_all2 eq_class.eq typargs1 typargs2"
   444   by (simp add: eq list_all2_eq [symmetric])
   444   by (simp add: eq list_all2_eq [symmetric])
   445 
   445 
   446 text {*
   446 text {*
   447   \noindent does not depend on instance @{text "monotype \<Colon> eq"}:
   447   \noindent does not depend on instance @{text "monotype \<Colon> eq"}:
   448 *}
   448 *}
   449 
   449 
   450 text %quoteme {*@{code_stmts "eq_class.eq :: monotype \<Rightarrow> monotype \<Rightarrow> bool" (SML)}*}
   450 text %quoteme {*@{code_stmts "eq_class.eq :: monotype \<Rightarrow> monotype \<Rightarrow> bool" (SML)}*}
   451 
   451 
   452 
   452 
   453 subsection {* Partiality *}
   453 subsection {* Explicit partiality *}
   454 
   454 
   455 text {* @{command "code_abort"}, examples: maps *}
   455 text {*
       
   456   Partiality usually enters the game by partial patterns, as
       
   457   in the following example, again for amortised queues:
       
   458 *}
       
   459 
       
   460 fun %quoteme strict_dequeue :: "'a queue \<Rightarrow> 'a \<times> 'a queue" where
       
   461   "strict_dequeue (Queue xs (y # ys)) = (y, Queue xs ys)"
       
   462   | "strict_dequeue (Queue xs []) =
       
   463       (case rev xs of y # ys \<Rightarrow> (y, Queue [] ys))"
       
   464 
       
   465 text {*
       
   466   \noindent In the corresponding code, there is no equation
       
   467   for the pattern @{term "Queue [] []"}:
       
   468 *}
       
   469 
       
   470 text %quoteme {*@{code_stmts strict_dequeue (consts) strict_dequeue (Haskell)}*}
       
   471 
       
   472 text {*
       
   473   \noindent In some cases it is desirable to have this
       
   474   pseudo-\qt{partiality} more explicitly, e.g.~as follows:
       
   475 *}
       
   476 
       
   477 axiomatization %quoteme empty_queue :: 'a
       
   478 
       
   479 function %quoteme strict_dequeue' :: "'a queue \<Rightarrow> 'a \<times> 'a queue" where
       
   480   "strict_dequeue' (Queue xs []) = (if xs = [] then empty_queue
       
   481      else strict_dequeue' (Queue [] (rev xs)))"
       
   482   | "strict_dequeue' (Queue xs (y # ys)) =
       
   483        (y, Queue xs ys)"
       
   484 by pat_completeness auto
       
   485 
       
   486 termination %quoteme strict_dequeue'
       
   487 by (relation "measure (\<lambda>q::'a queue. case q of Queue xs ys \<Rightarrow> length xs)") simp_all
       
   488 
       
   489 text {*
       
   490   \noindent For technical reasons the definition of
       
   491   @{const strict_dequeue'} is more involved since it requires
       
   492   a manual termination proof.  Apart from that observe that
       
   493   on the right hand side of its first equation the constant
       
   494   @{const empty_queue} occurs which is unspecified.
       
   495 
       
   496   Normally, if constants without any defining equations occur in
       
   497   a program, the code generator complains (since in most cases
       
   498   this is not what the user expects).  But such constants can also
       
   499   be thought of as function definitions with no equations which
       
   500   always fail, since there is never a successful pattern match
       
   501   on the left hand side.  In order to categorize a constant into
       
   502   that category explicitly, use @{command "code_abort"}:
       
   503 *}
       
   504 
       
   505 code_abort %quoteme empty_queue
       
   506 
       
   507 text {*
       
   508   \noindent Then the code generator will just insert an error or
       
   509   exception at the appropriate position:
       
   510 *}
       
   511 
       
   512 text %quoteme {*@{code_stmts strict_dequeue' (consts) empty_queue strict_dequeue' (Haskell)}*}
       
   513 
       
   514 text {*
       
   515   \noindent This feature however is rarely needed in practice.
       
   516   Note also that the @{text HOL} default setup already declares
       
   517   @{const undefined} as @{command "code_abort"}, which is most
       
   518   likely to be used in such situations.
       
   519 *}
   456 
   520 
   457 end
   521 end
       
   522