360 qed |
356 qed |
361 |
357 |
362 Two very simple example proofs are as follows. |
358 Two very simple example proofs are as follows. |
363 *} |
359 *} |
364 |
360 |
|
361 subsection {* EXERCISE 1 *} |
365 |
362 |
366 lemma eval_val: |
363 lemma eval_val: |
367 assumes a: "val t" |
364 assumes a: "val t" |
368 shows "t \<Down> t" |
365 shows "t \<Down> t" |
369 using a |
366 using a |
370 proof (induct) |
367 proof (induct) |
371 case (v_Lam x t) |
368 case (v_Lam x t) |
372 show "Lam [x]. t \<Down> Lam [x]. t" sorry |
369 show "Lam [x]. t \<Down> Lam [x]. t" sorry |
373 qed |
370 qed |
374 |
371 |
375 lemma eavl_to_val: |
372 subsection {* EXERCISE 2 *} |
|
373 |
|
374 text {* Fill the gaps in the proof below. *} |
|
375 |
|
376 lemma eval_to_val: |
376 assumes a: "t \<Down> t'" |
377 assumes a: "t \<Down> t'" |
377 shows "val t'" |
378 shows "val t'" |
378 using a |
379 using a |
379 proof (induct) |
380 proof (induct) |
380 case (e_Lam x t) |
381 case (e_Lam x t) |
381 show "val (Lam [x].t)" sorry |
382 show "val (Lam [x].t)" sorry |
382 next |
383 next |
383 case (e_App t1 x t t2 v v') |
384 case (e_App t1 x t t2 v v') |
|
385 -- {* all assumptions in this case *} |
384 have "t1 \<Down> Lam [x].t" by fact |
386 have "t1 \<Down> Lam [x].t" by fact |
385 have ih1: "val (Lam [x]. t)" by fact |
387 have ih1: "val (Lam [x]. t)" by fact |
386 have "t2 \<Down> v" by fact |
388 have "t2 \<Down> v" by fact |
387 have ih2: "val v" by fact |
389 have ih2: "val v" by fact |
388 have "t [x ::= v] \<Down> v'" by fact |
390 have "t [x ::= v] \<Down> v'" by fact |
389 have ih3: "val v'" by fact |
391 have ih3: "val v'" by fact |
|
392 |
390 show "val v'" sorry |
393 show "val v'" sorry |
391 qed |
394 qed |
392 |
395 |
393 |
396 |
394 text {* |
397 section {* Datatypes: Evaluation Contexts*} |
395 Just like gotos in the Basic programming language, labels often reduce |
398 |
396 the readability of proofs. Therefore one can use in Isar the notation |
399 text {* |
397 "then have" in order to feed a have-statement to the proof of |
|
398 the next have-statement. This is used in the second case below. |
|
399 *} |
|
400 |
|
401 |
|
402 |
|
403 text {* |
|
404 The label ih2 cannot be got rid of in this way, because it is used |
|
405 two lines below and we cannot rearrange them. We can still avoid the |
|
406 label by feeding a sequence of facts into a proof using the |
|
407 "moreover"-chaining mechanism: |
|
408 |
|
409 have "statement_1" \<dots> |
|
410 moreover |
|
411 have "statement_2" \<dots> |
|
412 \<dots> |
|
413 moreover |
|
414 have "statement_n" \<dots> |
|
415 ultimately have "statement" \<dots> |
|
416 |
|
417 In this chain, all "statement_i" can be used in the proof of the final |
|
418 "statement". With this we can simplify our proof further to: |
|
419 *} |
|
420 |
|
421 |
|
422 text {* |
|
423 While automatic proof procedures in Isabelle are not able to prove statements |
|
424 like "P = NP" assuming usual definitions for P and NP, they can automatically |
|
425 discharge the lemmas we just proved. For this we only have to set up the induction |
|
426 and auto will take care of the rest. This means we can write: |
|
427 *} |
|
428 |
|
429 |
|
430 |
|
431 |
|
432 section {* Datatypes: Evaluation Contexts *} |
|
433 |
|
434 text {* |
|
435 |
|
436 Datatypes can be defined in Isabelle as follows: we have to provide the name |
400 Datatypes can be defined in Isabelle as follows: we have to provide the name |
437 of the datatype and list its type-constructors. Each type-constructor needs |
401 of the datatype and a list its type-constructors. Each type-constructor needs |
438 to have the information about the types of its arguments, and optionally |
402 to have the information about the types of its arguments, and optionally |
439 can also contain some information about pretty syntax. For example, we like |
403 can also contain some information about pretty syntax. For example, we like |
440 to write "\<box>" for holes. |
404 to write "\<box>" for holes. |
441 *} |
405 *} |
442 |
406 |
443 datatype ctx = |
407 datatype ctx = |
444 Hole ("\<box>") |
408 Hole ("\<box>") |
445 | CAppL "ctx" "lam" |
409 | CAppL "ctx" "lam" |
446 | CAppR "lam" "ctx" |
410 | CAppR "lam" "ctx" |
447 |
411 |
456 |
420 |
457 text {* |
421 text {* |
458 Try and see what happens if you apply a Hole to a Hole? |
422 Try and see what happens if you apply a Hole to a Hole? |
459 *} |
423 *} |
460 |
424 |
|
425 |
|
426 section {* Machines for Evaluation *} |
|
427 |
461 type_synonym ctxs = "ctx list" |
428 type_synonym ctxs = "ctx list" |
462 |
429 |
463 inductive |
430 inductive |
464 machine :: "lam \<Rightarrow> ctxs \<Rightarrow>lam \<Rightarrow> ctxs \<Rightarrow> bool" ("<_,_> \<mapsto> <_,_>" [60, 60, 60, 60] 60) |
431 machine :: "lam \<Rightarrow> ctxs \<Rightarrow>lam \<Rightarrow> ctxs \<Rightarrow> bool" ("<_,_> \<mapsto> <_,_>" [60, 60, 60, 60] 60) |
465 where |
432 where |
466 m1[intro]: "<App t1 t2,Es> \<mapsto> <t1,(CAppL \<box> t2) # Es>" |
433 m1: "<App t1 t2, Es> \<mapsto> <t1, (CAppL \<box> t2) # Es>" |
467 | m2[intro]: "val v \<Longrightarrow> <v,(CAppL \<box> t2) # Es> \<mapsto> <t2,(CAppR v \<box>) # Es>" |
434 | m2: "val v \<Longrightarrow> <v, (CAppL \<box> t2) # Es> \<mapsto> <t2, (CAppR v \<box>) # Es>" |
468 | m3[intro]: "val v \<Longrightarrow> <v,(CAppR (Lam [x].t) \<box>) # Es> \<mapsto> <t[x ::= v],Es>" |
435 | m3: "val v \<Longrightarrow> <v, (CAppR (Lam [x].t) \<box>) # Es> \<mapsto> <t[x ::= v], Es>" |
469 |
|
470 |
436 |
471 text {* |
437 text {* |
472 Since the machine defined above only performs a single reduction, |
438 Since the machine defined above only performs a single reduction, |
473 we need to define the transitive closure of this machine. *} |
439 we need to define the transitive closure of this machine. *} |
474 |
440 |
475 inductive |
441 inductive |
476 machines :: "lam \<Rightarrow> ctxs \<Rightarrow> lam \<Rightarrow> ctxs \<Rightarrow> bool" ("<_,_> \<mapsto>* <_,_>" [60, 60, 60, 60] 60) |
442 machines :: "lam \<Rightarrow> ctxs \<Rightarrow> lam \<Rightarrow> ctxs \<Rightarrow> bool" ("<_,_> \<mapsto>* <_,_>" [60, 60, 60, 60] 60) |
477 where |
443 where |
478 ms1[intro]: "<t,Es> \<mapsto>* <t,Es>" |
444 ms1: "<t,Es> \<mapsto>* <t,Es>" |
479 | ms2[intro]: "\<lbrakk><t1,Es1> \<mapsto> <t2,Es2>; <t2,Es2> \<mapsto>* <t3,Es3>\<rbrakk> \<Longrightarrow> <t1,Es1> \<mapsto>* <t3,Es3>" |
445 | ms2: "\<lbrakk><t1,Es1> \<mapsto> <t2,Es2>; <t2,Es2> \<mapsto>* <t3,Es3>\<rbrakk> \<Longrightarrow> <t1,Es1> \<mapsto>* <t3,Es3>" |
480 |
446 |
481 lemma |
447 declare machine.intros[intro] machines.intros[intro] |
|
448 |
|
449 section {* EXERCISE 3 *} |
|
450 |
|
451 text {* |
|
452 We need to show that the machines-relation is transitive. |
|
453 Fill in the gaps below. |
|
454 *} |
|
455 |
|
456 lemma ms3[intro]: |
482 assumes a: "<e1, Es1> \<mapsto>* <e2, Es2>" |
457 assumes a: "<e1, Es1> \<mapsto>* <e2, Es2>" |
483 and b: "<e2, Es2> \<mapsto>* <e3, Es3>" |
458 and b: "<e2, Es2> \<mapsto>* <e3, Es3>" |
484 shows "<e1, Es1> \<mapsto>* <e3, Es3>" |
459 shows "<e1, Es1> \<mapsto>* <e3, Es3>" |
485 using a b |
460 using a b |
486 proof(induct) |
461 proof(induct) |
487 case (ms1 e1 Es1) |
462 case (ms1 e1 Es1) |
488 have c: "<e1, Es1> \<mapsto>* <e3, Es3>" by fact |
463 have c: "<e1, Es1> \<mapsto>* <e3, Es3>" by fact |
489 then show "<e1, Es1> \<mapsto>* <e3, Es3>" by simp |
464 |
|
465 show "<e1, Es1> \<mapsto>* <e3, Es3>" sorry |
490 next |
466 next |
491 case (ms2 e1 Es1 e2 Es2 e2' Es2') |
467 case (ms2 e1 Es1 e2 Es2 e2' Es2') |
492 have ih: "<e2', Es2'> \<mapsto>* <e3, Es3> \<Longrightarrow> <e2, Es2> \<mapsto>* <e3, Es3>" by fact |
468 have ih: "<e2', Es2'> \<mapsto>* <e3, Es3> \<Longrightarrow> <e2, Es2> \<mapsto>* <e3, Es3>" by fact |
493 have d1: "<e2', Es2'> \<mapsto>* <e3, Es3>" by fact |
469 have d1: "<e2', Es2'> \<mapsto>* <e3, Es3>" by fact |
494 have d2: "<e1, Es1> \<mapsto> <e2, Es2>" by fact |
470 have d2: "<e1, Es1> \<mapsto> <e2, Es2>" by fact |
495 show "<e1, Es1> \<mapsto>* <e3, Es3>" using d1 d2 ih by blast |
471 |
496 qed |
472 show "<e1, Es1> \<mapsto>* <e3, Es3>" sorry |
497 |
473 qed |
498 text {* |
474 |
499 Just like gotos in the Basic programming language, labels can reduce |
475 text {* |
|
476 Just like gotos in the Basic programming language, labels often reduce |
500 the readability of proofs. Therefore one can use in Isar the notation |
477 the readability of proofs. Therefore one can use in Isar the notation |
501 "then have" in order to feed a have-statement to the proof of |
478 "then have" in order to feed a have-statement to the proof of |
502 the next have-statement. In the proof below this has been used |
479 the next have-statement. This is used in the second case below. |
503 in order to get rid of the labels c and d1. |
480 *} |
504 *} |
481 |
505 |
|
506 lemma |
482 lemma |
507 assumes a: "<e1, Es1> \<mapsto>* <e2, Es2>" |
483 assumes a: "<e1, Es1> \<mapsto>* <e2, Es2>" |
508 and b: "<e2, Es2> \<mapsto>* <e3, Es3>" |
484 and b: "<e2, Es2> \<mapsto>* <e3, Es3>" |
509 shows "<e1, Es1> \<mapsto>* <e3, Es3>" |
485 shows "<e1, Es1> \<mapsto>* <e3, Es3>" |
510 using a b |
486 using a b |
518 then have d3: "<e2, Es2> \<mapsto>* <e3, Es3>" using ih by simp |
494 then have d3: "<e2, Es2> \<mapsto>* <e3, Es3>" using ih by simp |
519 have d2: "<e1, Es1> \<mapsto> <e2, Es2>" by fact |
495 have d2: "<e1, Es1> \<mapsto> <e2, Es2>" by fact |
520 show "<e1, Es1> \<mapsto>* <e3, Es3>" using d2 d3 by auto |
496 show "<e1, Es1> \<mapsto>* <e3, Es3>" using d2 d3 by auto |
521 qed |
497 qed |
522 |
498 |
|
499 text {* |
|
500 The label ih2 cannot be got rid of in this way, because it is used |
|
501 two lines below and we cannot rearrange them. We can still avoid the |
|
502 label by feeding a sequence of facts into a proof using the |
|
503 "moreover"-chaining mechanism: |
|
504 |
|
505 have "statement_1" \<dots> |
|
506 moreover |
|
507 have "statement_2" \<dots> |
|
508 \<dots> |
|
509 moreover |
|
510 have "statement_n" \<dots> |
|
511 ultimately have "statement" \<dots> |
|
512 |
|
513 In this chain, all "statement_i" can be used in the proof of the final |
|
514 "statement". With this we can simplify our proof further to: |
|
515 *} |
|
516 |
523 lemma |
517 lemma |
524 assumes a: "<e1, Es1> \<mapsto>* <e2, Es2>" |
518 assumes a: "<e1, Es1> \<mapsto>* <e2, Es2>" |
525 and b: "<e2, Es2> \<mapsto>* <e3, Es3>" |
519 and b: "<e2, Es2> \<mapsto>* <e3, Es3>" |
526 shows "<e1, Es1> \<mapsto>* <e3, Es3>" |
520 shows "<e1, Es1> \<mapsto>* <e3, Es3>" |
527 using a b |
521 using a b |
537 have "<e1, Es1> \<mapsto> <e2, Es2>" by fact |
531 have "<e1, Es1> \<mapsto> <e2, Es2>" by fact |
538 ultimately show "<e1, Es1> \<mapsto>* <e3, Es3>" by auto |
532 ultimately show "<e1, Es1> \<mapsto>* <e3, Es3>" by auto |
539 qed |
533 qed |
540 |
534 |
541 |
535 |
542 lemma ms3[intro]: |
536 text {* |
|
537 While automatic proof procedures in Isabelle are not able to prove statements |
|
538 like "P = NP" assuming usual definitions for P and NP, they can automatically |
|
539 discharge the lemmas we just proved. For this we only have to set up the induction |
|
540 and auto will take care of the rest. This means we can write: |
|
541 *} |
|
542 |
|
543 lemma |
|
544 assumes a: "val t" |
|
545 shows "t \<Down> t" |
|
546 using a by (induct) (auto) |
|
547 |
|
548 lemma |
|
549 assumes a: "t \<Down> t'" |
|
550 shows "val t'" |
|
551 using a by (induct) (auto) |
|
552 |
|
553 lemma |
543 assumes a: "<e1, Es1> \<mapsto>* <e2, Es2>" |
554 assumes a: "<e1, Es1> \<mapsto>* <e2, Es2>" |
544 and b: "<e2, Es2> \<mapsto>* <e3, Es3>" |
555 and b: "<e2, Es2> \<mapsto>* <e3, Es3>" |
545 shows "<e1, Es1> \<mapsto>* <e3, Es3>" |
556 shows "<e1, Es1> \<mapsto>* <e3, Es3>" |
546 using a b by (induct) (auto) |
557 using a b by (induct) (auto) |
547 |
558 |
548 lemma eval_to_val: (* fixme: done above *) |
559 |
549 assumes a: "t \<Down> t'" |
560 section {* EXERCISE 4 *} |
550 shows "val t'" |
561 |
551 using a by (induct) (auto) |
562 text {* |
|
563 The point of the machine is that it simulates the evaluation |
|
564 relation. Therefore we like to prove the following: |
|
565 *} |
552 |
566 |
553 theorem |
567 theorem |
554 assumes a: "t \<Down> t'" |
568 assumes a: "t \<Down> t'" |
555 shows "<t, []> \<mapsto>* <t', []>" |
569 shows "<t, []> \<mapsto>* <t', []>" |
556 using a |
570 using a |
565 have ih1: "<t1, []> \<mapsto>* <Lam [x].t, []>" by fact |
579 have ih1: "<t1, []> \<mapsto>* <Lam [x].t, []>" by fact |
566 have a2: "t2 \<Down> v'" by fact |
580 have a2: "t2 \<Down> v'" by fact |
567 have ih2: "<t2, []> \<mapsto>* <v', []>" by fact |
581 have ih2: "<t2, []> \<mapsto>* <v', []>" by fact |
568 have a3: "t[x::=v'] \<Down> v" by fact |
582 have a3: "t[x::=v'] \<Down> v" by fact |
569 have ih3: "<t[x::=v'], []> \<mapsto>* <v, []>" by fact |
583 have ih3: "<t[x::=v'], []> \<mapsto>* <v, []>" by fact |
|
584 |
570 -- {* your reasoning *} |
585 -- {* your reasoning *} |
571 show "<App t1 t2, []> \<mapsto>* <v, []>" sorry |
586 show "<App t1 t2, []> \<mapsto>* <v, []>" sorry |
572 qed |
587 qed |
|
588 |
573 |
589 |
574 text {* |
590 text {* |
575 Again the automatic tools in Isabelle can discharge automatically |
591 Again the automatic tools in Isabelle can discharge automatically |
576 of the routine work in these proofs. We can write: |
592 of the routine work in these proofs. We can write: |
577 *} |
593 *} |
684 have ih: "(Es1 @ Es2)\<down> = Es2\<down> \<odot> Es1\<down>" by fact |
708 have ih: "(Es1 @ Es2)\<down> = Es2\<down> \<odot> Es1\<down>" by fact |
685 |
709 |
686 show "((E # Es1) @ Es2)\<down> = Es2\<down> \<odot> (E # Es1)\<down>" sorry |
710 show "((E # Es1) @ Es2)\<down> = Es2\<down> \<odot> (E # Es1)\<down>" sorry |
687 qed |
711 qed |
688 |
712 |
689 |
|
690 text {* |
713 text {* |
691 The last proof involves several steps of equational reasoning. |
714 The last proof involves several steps of equational reasoning. |
692 Isar provides some convenient means to express such equational |
715 Isar provides some convenient means to express such equational |
693 reasoning in a much cleaner fashion using the "also have" |
716 reasoning in a much cleaner fashion using the "also have" |
694 construction. |
717 construction. |
695 *} |
718 *} |
696 |
|
697 |
719 |
698 lemma |
720 lemma |
699 shows "(Es1 @ Es2)\<down> = (Es2\<down>) \<odot> (Es1\<down>)" |
721 shows "(Es1 @ Es2)\<down> = (Es2\<down>) \<odot> (Es1\<down>)" |
700 proof (induct Es1) |
722 proof (induct Es1) |
701 case Nil |
723 case Nil |
702 show "([] @ Es2)\<down> = Es2\<down> \<odot> []\<down>" using neut_hole by simp |
724 show "([] @ Es2)\<down> = Es2\<down> \<odot> []\<down>" using neut_hole by simp |
703 next |
725 next |
704 case (Cons E Es1) |
726 case (Cons E Es1) |
705 have ih: "(Es1 @ Es2)\<down> = Es2\<down> \<odot> Es1\<down>" by fact |
727 have ih: "(Es1 @ Es2)\<down> = Es2\<down> \<odot> Es1\<down>" by fact |
706 have "((E # Es1) @ Es2)\<down> = (Es1 @ Es2)\<down> \<odot> E" by simp |
728 have "((E # Es1) @ Es2)\<down> = (E # (Es1 @ Es2))\<down>" by simp |
|
729 also have "\<dots> = (Es1 @ Es2)\<down> \<odot> E" by simp |
707 also have "\<dots> = (Es2\<down> \<odot> Es1\<down>) \<odot> E" using ih by simp |
730 also have "\<dots> = (Es2\<down> \<odot> Es1\<down>) \<odot> E" using ih by simp |
708 also have "\<dots> = Es2\<down> \<odot> (Es1\<down> \<odot> E)" using odot_assoc by simp |
731 also have "\<dots> = Es2\<down> \<odot> (Es1\<down> \<odot> E)" using compose_assoc by simp |
709 also have "\<dots> = Es2\<down> \<odot> (E # Es1)\<down>" by simp |
732 also have "\<dots> = Es2\<down> \<odot> (E # Es1)\<down>" by simp |
710 finally show "((E # Es1) @ Es2)\<down> = Es2\<down> \<odot> (E # Es1)\<down>" by simp |
733 finally show "((E # Es1) @ Es2)\<down> = Es2\<down> \<odot> (E # Es1)\<down>" by simp |
711 qed |
734 qed |
712 |
735 |
713 |
736 |
714 |
|
715 end |
737 end |
716 |
738 |