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 |