comparison src/Subset.v @ 73:535e1cd17d9a

maybe and sumor
author Adam Chlipala <adamc@hcoop.net>
date Fri, 03 Oct 2008 14:14:28 -0400
parents 839d159cac5d
children a21447f76aad
comparison
equal deleted inserted replaced
72:839d159cac5d 73:535e1cd17d9a
419 </pre># *) 419 </pre># *)
420 420
421 421
422 (** * Partial Subset Types *) 422 (** * Partial Subset Types *)
423 423
424 (** Our final implementation of dependent predecessor used a very specific argument type to ensure that execution could always complete normally. Sometimes we want to allow execution to fail, and we want a more principled way of signaling that than returning a default value, as [pred] does for [0]. One approach is to define this type family [maybe], which is a version of [sig] that allows obligation-free failure. *)
425
424 Inductive maybe (A : Type) (P : A -> Prop) : Set := 426 Inductive maybe (A : Type) (P : A -> Prop) : Set :=
425 | Unknown : maybe P 427 | Unknown : maybe P
426 | Found : forall x : A, P x -> maybe P. 428 | Found : forall x : A, P x -> maybe P.
427 429
430 (** We can define some new notations, analogous to those we defined for subset types. *)
431
428 Notation "{{ x | P }}" := (maybe (fun x => P)). 432 Notation "{{ x | P }}" := (maybe (fun x => P)).
429 Notation "??" := (Unknown _). 433 Notation "??" := (Unknown _).
430 Notation "[[ x ]]" := (Found _ x _). 434 Notation "[[ x ]]" := (Found _ x _).
435
436 (** Now our next version of [pred] is trivial to write. *)
437
438 Definition pred_strong6 (n : nat) : {{m | n = S m}}.
439 refine (fun n =>
440 match n return {{m | n = S m}} with
441 | O => ??
442 | S n' => [[n']]
443 end); trivial.
444 Defined.
445
446 (** Because we used [maybe], one valid implementation of the type we gave [pred_strong6] would return [??] in every case. We can strengthen the type to rule out such vacuous implementations, and the type family [sumor] from the standard library provides the easiest starting point. For type [A] and proposition [B], [A + {B}] desugars to [sumor A B], whose values are either values of [A] or proofs of [B]. *)
447
448 Print sumor.
449 (** [[
450
451 Inductive sumor (A : Type) (B : Prop) : Type :=
452 inleft : A -> A + {B} | inright : B -> A + {B}
453 For inleft: Argument A is implicit
454 For inright: Argument B is implicit
455 ]] *)
456
457 (** We add notations for easy use of the [sumor] constructors. The second notation is specialized to [sumor]s whose [A] parameters are instantiated with regular subset types, since this is how we will use [sumor] below. *)
458
459 Notation "!!" := (inright _ _).
460 Notation "[[[ x ]]]" := (inleft _ [x]).
461
462 (** Now we are ready to give the final version of possibly-failing predecessor. The [sumor]-based type that we use is maximally expressive; any implementation of the type has the same input-output behavior. *)
463
464 Definition pred_strong7 (n : nat) : {m : nat | n = S m} + {n = 0}.
465 refine (fun n =>
466 match n return {m : nat | n = S m} + {n = 0} with
467 | O => !!
468 | S n' => [[[n']]]
469 end); trivial.
470 Defined.
471
472
473 (** * Monadic Notations *)
474
475 (** We can treat [maybe] like a monad, in the same way that the Haskell [Maybe] type is interpreted as a failure monad. Our [maybe] has the wrong type to be a literal monad, but a "bind"-like notation will still be helpful. *)
431 476
432 Notation "x <- e1 ; e2" := (match e1 with 477 Notation "x <- e1 ; e2" := (match e1 with
433 | Unknown => ?? 478 | Unknown => ??
434 | Found x _ => e2 479 | Found x _ => e2
435 end) 480 end)
436 (right associativity, at level 60). 481 (right associativity, at level 60).
437 482
438 Notation "e1 ;; e2" := (if e1 then e2 else ??) 483 (** The meaning of [x <- e1; e2] is: First run [e1]. If it fails to find an answer, then announce failure for our derived computation, too. If [e1] %\textit{%#<i>#does#</i>#%}% find an answer, pass that answer on to [e2] to find the final result. The variable [x] can be considered bound in [e2].
439 (right associativity, at level 60). 484
485 This notation is very helpful for composing richly-typed procedures. For instance, here is a very simple implementation of a function to take the predecessors of two naturals at once. *)
486
487 Definition doublePred (n1 n2 : nat) : {{p | n1 = S (fst p) /\ n2 = S (snd p)}}.
488 refine (fun n1 n2 =>
489 m1 <- pred_strong6 n1;
490 m2 <- pred_strong6 n2;
491 [[(m1, m2)]]); tauto.
492 Defined.
493
494 (** We can build a [sumor] version of the "bind" notation and use it to write a similarly straightforward version of this function. *)
495
496 (** printing <-- $\longleftarrow$ *)
497
498 Notation "x <-- e1 ; e2" := (match e1 with
499 | inright _ => !!
500 | inleft (exist x _) => e2
501 end)
502 (right associativity, at level 60).
503
504 (** printing * $\times$ *)
505
506 Definition doublePred' (n1 n2 : nat) : {p : nat * nat | n1 = S (fst p) /\ n2 = S (snd p)}
507 + {n1 = 0 \/ n2 = 0}.
508 refine (fun n1 n2 =>
509 m1 <-- pred_strong7 n1;
510 m2 <-- pred_strong7 n2;
511 [[[(m1, m2)]]]); tauto.
512 Defined.
440 513
441 514
442 (** * A Type-Checking Example *) 515 (** * A Type-Checking Example *)
443 516
444 Inductive exp : Set := 517 Inductive exp : Set :=
464 -> hasType (And e1 e2) TBool. 537 -> hasType (And e1 e2) TBool.
465 538
466 Definition eq_type_dec : forall (t1 t2 : type), {t1 = t2} + {t1 <> t2}. 539 Definition eq_type_dec : forall (t1 t2 : type), {t1 = t2} + {t1 <> t2}.
467 decide equality. 540 decide equality.
468 Defined. 541 Defined.
542
543 Notation "e1 ;; e2" := (if e1 then e2 else ??)
544 (right associativity, at level 60).
469 545
470 Definition typeCheck (e : exp) : {{t | hasType e t}}. 546 Definition typeCheck (e : exp) : {{t | hasType e t}}.
471 Hint Constructors hasType. 547 Hint Constructors hasType.
472 548
473 refine (fix F (e : exp) : {{t | hasType e t}} := 549 refine (fix F (e : exp) : {{t | hasType e t}} :=
490 Defined. 566 Defined.
491 567
492 Eval simpl in typeCheck (Nat 0). 568 Eval simpl in typeCheck (Nat 0).
493 Eval simpl in typeCheck (Plus (Nat 1) (Nat 2)). 569 Eval simpl in typeCheck (Plus (Nat 1) (Nat 2)).
494 Eval simpl in typeCheck (Plus (Nat 1) (Bool false)). 570 Eval simpl in typeCheck (Plus (Nat 1) (Bool false)).
571
572 Print sumor.
573
574
575
576 Notation "e1 ;;; e2" := (if e1 then e2 else !!)
577 (right associativity, at level 60).
578
579 Theorem hasType_det : forall e t1,
580 hasType e t1
581 -> forall t2,
582 hasType e t2
583 -> t1 = t2.
584 induction 1; inversion 1; crush.
585 Qed.
586
587 Definition typeCheck' (e : exp) : {t : type | hasType e t} + {forall t, ~hasType e t}.
588 Hint Constructors hasType.
589 Hint Resolve hasType_det.
590
591 refine (fix F (e : exp) : {t : type | hasType e t} + {forall t, ~hasType e t} :=
592 match e return {t : type | hasType e t} + {forall t, ~hasType e t} with
593 | Nat _ => [[[TNat]]]
594 | Plus e1 e2 =>
595 t1 <-- F e1;
596 t2 <-- F e2;
597 eq_type_dec t1 TNat;;;
598 eq_type_dec t2 TNat;;;
599 [[[TNat]]]
600 | Bool _ => [[[TBool]]]
601 | And e1 e2 =>
602 t1 <-- F e1;
603 t2 <-- F e2;
604 eq_type_dec t1 TBool;;;
605 eq_type_dec t2 TBool;;;
606 [[[TBool]]]
607 end); clear F; crush' tt hasType; eauto.
608 Defined.
609
610 Eval simpl in typeCheck' (Nat 0).
611 Eval simpl in typeCheck' (Plus (Nat 1) (Nat 2)).
612 Eval simpl in typeCheck' (Plus (Nat 1) (Bool false)).