diff src/GeneralRec.v @ 352:ab60b10890ed

Non-termination monad
author Adam Chlipala <adam@chlipala.net>
date Wed, 26 Oct 2011 16:57:11 -0400
parents bb1a470c1757
children 3322367e955d
line wrap: on
line diff
--- a/src/GeneralRec.v	Wed Oct 26 15:12:21 2011 -0400
+++ b/src/GeneralRec.v	Wed Oct 26 16:57:11 2011 -0400
@@ -275,3 +275,305 @@
 ]]
 
   Some more recent Coq features provide more convenient syntax for defining recursive functions.  Interested readers can consult the Coq manual about the commands %\index{Function}%[Function] and %\index{Program Fixpoint}%[Program Fixpoint]. *)
+
+
+(** * A Non-Termination Monad *)
+
+Section computation.
+  Variable A : Type.
+
+  Definition computation :=
+    {f : nat -> option A
+      | forall (n : nat) (v : A),
+	f n = Some v
+	-> forall (n' : nat), n' >= n
+	  -> f n' = Some v}.
+
+  Definition runTo (m : computation) (n : nat) (v : A) :=
+    proj1_sig m n = Some v.
+
+  Definition run (m : computation) (v : A) :=
+    exists n, runTo m n v.
+End computation.
+
+Hint Unfold runTo.
+
+Ltac run' := unfold run, runTo in *; try red; crush;
+  repeat (match goal with
+            | [ _ : proj1_sig ?E _ = _ |- _ ] =>
+              match goal with
+                | [ x : _ |- _ ] =>
+                  match x with
+                    | E => destruct E
+                  end
+              end
+            | [ |- context[match ?M with exist _ _ => _ end] ] => let Heq := fresh "Heq" in
+              case_eq M; intros ? ? Heq; try rewrite Heq in *; try subst
+            | [ _ : context[match ?M with exist _ _ => _ end] |- _ ] => let Heq := fresh "Heq" in
+              case_eq M; intros ? ? Heq; try rewrite Heq in *; subst
+            | [ H : forall n v, ?E n = Some v -> _,
+                _ : context[match ?E ?N with Some _ => _ | None => _ end] |- _ ] =>
+              specialize (H N); destruct (E N); try rewrite (H _ (refl_equal _)) by auto; try discriminate
+            | [ H : forall n v, ?E n = Some v -> _, H' : ?E _ = Some _ |- _ ] => rewrite (H _ _ H') by auto
+          end; simpl in *); eauto 7.
+
+Ltac run := run'; repeat (match goal with
+                            | [ H : forall n v, ?E n = Some v -> _
+                                |- context[match ?E ?N with Some _ => _ | None => _ end] ] =>
+                              specialize (H N); destruct (E N); try rewrite (H _ (refl_equal _)) by auto; try discriminate
+                          end; run').
+
+Lemma ex_irrelevant : forall P : Prop, P -> exists n : nat, P.
+  exists 0; auto.
+Qed.
+
+Hint Resolve ex_irrelevant.
+
+Require Import Max.
+
+Ltac max := intros n m; generalize (max_spec_le n m); crush.
+
+Lemma max_1 : forall n m, max n m >= n.
+  max.
+Qed.
+
+Lemma max_2 : forall n m, max n m >= m.
+  max.
+Qed.
+
+Hint Resolve max_1 max_2.
+
+Lemma ge_refl : forall n, n >= n.
+  crush.
+Qed.
+
+Hint Resolve ge_refl.
+
+Hint Extern 1 => match goal with
+                   | [ H : _ = exist _ _ _ |- _ ] => rewrite H
+                 end.
+
+Section Bottom.
+  Variable A : Type.
+
+  Definition Bottom : computation A.
+    exists (fun _ : nat => @None A); abstract run.
+  Defined.
+
+  Theorem run_Bottom : forall v, ~run Bottom v.
+    run.
+  Qed.
+End Bottom.
+
+Section Return.
+  Variable A : Type.
+  Variable v : A.
+
+  Definition Return : computation A.
+    intros; exists (fun _ : nat => Some v); abstract run.
+  Defined.
+
+  Theorem run_Return : run Return v.
+    run.
+  Qed.
+
+  Theorem run_Return_inv : forall x, run Return x -> x = v.
+    run.
+  Qed.
+End Return.
+
+Hint Resolve run_Return.
+
+Section Bind.
+  Variables A B : Type.
+  Variable m1 : computation A.
+  Variable m2 : A -> computation B.
+
+  Definition Bind : computation B.
+    exists (fun n =>
+      let (f1, Hf1) := m1 in
+      match f1 n with
+	| None => None
+	| Some v =>
+	  let (f2, Hf2) := m2 v in
+	    f2 n
+      end); abstract run.
+  Defined.
+
+  Require Import Max.
+
+  Theorem run_Bind : forall (v1 : A) (v2 : B),
+    run m1 v1
+    -> run (m2 v1) v2
+    -> run Bind v2.
+    run; match goal with
+           | [ x : nat, y : nat |- _ ] => exists (max x y)
+         end; run.
+  Qed.
+
+  Theorem run_Bind_inv : forall (v2 : B),
+    run Bind v2
+    -> exists v1 : A,
+      run m1 v1
+      /\ run (m2 v1) v2.
+    run.
+  Qed.
+End Bind.
+
+Hint Resolve run_Bind.
+
+Notation "x <- m1 ; m2" :=
+  (Bind m1 (fun x => m2)) (right associativity, at level 70).
+
+Definition meq A (m1 m2 : computation A) := forall n, proj1_sig m1 n = proj1_sig m2 n.
+
+Theorem left_identity : forall A B (a : A) (f : A -> computation B),
+  meq (Bind (Return a) f) (f a).
+  run.
+Qed.
+
+Theorem right_identity : forall A (m : computation A),
+  meq (Bind m (@Return _)) m.
+  run.
+Qed.
+
+Theorem associativity : forall A B C (m : computation A) (f : A -> computation B) (g : B -> computation C),
+  meq (Bind (Bind m f) g) (Bind m (fun x => Bind (f x) g)).
+  run.
+Qed.
+
+Section monotone_runTo.
+  Variable A : Type.
+  Variable c : computation A.
+  Variable v : A.
+
+  Theorem monotone_runTo : forall (n1 : nat),
+    runTo c n1 v
+    -> forall n2, n2 >= n1
+      -> runTo c n2 v.
+    run.
+  Qed.
+End monotone_runTo.
+
+Hint Resolve monotone_runTo.
+
+Section lattice.
+  Variable A : Type.
+
+  Definition leq (x y : option A) :=
+    forall v, x = Some v -> y = Some v.
+End lattice.
+
+Hint Unfold leq.
+
+Section Fix.
+  Variables A B : Type.
+  Variable f : (A -> computation B) -> (A -> computation B).
+
+  Hypothesis f_continuous : forall n v v1 x,
+    runTo (f v1 x) n v
+    -> forall (v2 : A -> computation B),
+      (forall x, leq (proj1_sig (v1 x) n) (proj1_sig (v2 x) n))
+      -> runTo (f v2 x) n v.
+
+  Fixpoint Fix' (n : nat) (x : A) : computation B :=
+    match n with
+      | O => Bottom _
+      | S n' => f (Fix' n') x
+    end.
+
+  Hint Extern 1 (_ >= _) => omega.
+  Hint Unfold leq.
+
+  Lemma Fix'_ok : forall steps n x v, proj1_sig (Fix' n x) steps = Some v
+    -> forall n', n' >= n
+      -> proj1_sig (Fix' n' x) steps = Some v.
+    unfold runTo in *; induction n; crush;
+      match goal with
+        | [ H : _ >= _ |- _ ] => inversion H; crush; eauto
+      end.
+  Qed.
+
+  Hint Resolve Fix'_ok.
+
+  Hint Extern 1 (proj1_sig _ _ = _) => simpl;
+    match goal with
+      | [ |- proj1_sig ?E _ = _ ] => eapply (proj2_sig E)
+    end.
+
+  Definition Fix : A -> computation B.
+    intro x; exists (fun n => proj1_sig (Fix' n x) n); abstract run.
+  Defined.
+
+  Definition extensional (f : (A -> computation B) -> (A -> computation B)) := 
+    forall g1 g2 n,
+      (forall x, proj1_sig (g1 x) n = proj1_sig (g2 x) n)
+      -> forall x, proj1_sig (f g1 x) n = proj1_sig (f g2 x) n.
+
+  Hypothesis f_extensional : extensional f.
+
+  Theorem run_Fix : forall x v,
+    run (f Fix x) v
+    -> run (Fix x) v.
+    run; match goal with
+           | [ n : nat |- _ ] => exists (S n); eauto
+         end.
+  Qed.
+End Fix.
+
+Hint Resolve run_Fix.
+
+Lemma leq_Some : forall A (x y : A), leq (Some x) (Some y)
+  -> x = y.
+  intros ? ? ? H; generalize (H _ (refl_equal _)); crush.
+Qed.
+
+Lemma leq_None : forall A (x y : A), leq (Some x) None
+  -> False.
+  intros ? ? ? H; generalize (H _ (refl_equal _)); crush.
+Qed.
+
+Definition mergeSort' : forall A, (A -> A -> bool) -> list A -> computation (list A).
+  refine (fun A le => Fix
+    (fun (mergeSort : list A -> computation (list A))
+      (ls : list A) =>
+      if le_lt_dec 2 (length ls)
+	then let lss := partition ls in
+          ls1 <- mergeSort (fst lss);
+          ls2 <- mergeSort (snd lss);
+          Return (merge le ls1 ls2)
+	else Return ls) _); abstract (run;
+          repeat (match goal with
+                    | [ |- context[match ?E with O => _ | S _ => _ end] ] => destruct E
+                  end; run);
+          repeat match goal with
+                   | [ H : forall x, leq (proj1_sig (?f x) _) (proj1_sig (?g x) _) |- _ ] =>
+                     match goal with
+                       | [ H1 : f ?arg = _, H2 : g ?arg = _ |- _ ] =>
+                         generalize (H arg); rewrite H1; rewrite H2; clear H1 H2; simpl; intro
+                     end
+                 end; run; repeat match goal with
+                                    | [ H : _ |- _ ] => (apply leq_None in H; tauto) || (apply leq_Some in H; subst)
+                                  end; auto).
+Defined.
+
+Print mergeSort'.
+
+Lemma test_mergeSort' : run (mergeSort' leb (1 :: 2 :: 36 :: 8 :: 19 :: nil))
+  (1 :: 2 :: 8 :: 19 :: 36 :: nil).
+  exists 4; reflexivity.
+Qed.
+
+Definition looper : bool -> computation unit.
+  refine (Fix (fun looper (b : bool) =>
+    if b then Return tt else looper b) _);
+  abstract (unfold leq in *; run;
+    repeat match goal with
+             | [ x : unit |- _ ] => destruct x
+             | [ x : bool |- _ ] => destruct x
+           end; auto).
+Defined.
+
+Lemma test_looper : run (looper true) tt.
+  exists 1; reflexivity.
+Qed.