(* -------------------------------------------------------------------------- *) (* The [bind] combinator of the option monad. *) Definition bind {A B} (f : option A) (k : A -> option B) : option B := match f with | None => None | Some a => k a end. (* The standard syntactic sugar for [bind]. [f >>= k] can be read as ``first do [f]; then, if successful, with the result of [f], do [k]''. *) Notation "f >>= k" := (bind f k) (at level 55). (* -------------------------------------------------------------------------- *) (* These lemmas help prove an equation of the form [f >>= k = b]. *) Lemma prove_bind_None: forall {A B} {f} {k : A -> option B}, f = None -> f >>= k = None. Proof. intros. subst. eauto. Qed. Lemma prove_bind_Some: forall {A B} {f} {k : A -> option B} {a b}, f = Some a -> k a = b -> f >>= k = b. Proof. intros. subst. eauto. Qed. (* This lemma helps exploit an equation of the form [f >>= k = Some b]. *) Lemma invert_bind_Some: forall {A B} {f} {k : A -> option B} {b}, f >>= k = Some b -> exists a, f = Some a /\ k a = Some b. Proof. destruct f; simpl; intros. { eauto. } { congruence. } Qed. Ltac invert_bind_Some := match goal with h: ?f >>= _ = Some _ |- _ => let heq := fresh in generalize (invert_bind_Some h); clear h; intros (?&?&h) end. (* -------------------------------------------------------------------------- *) (* The standard ordering on options, where [None] is less defined then everything, and every element of the form [Some a] is less defined than itself only. *) Definition less_defined {A} (o1 o2 : option A) := forall a, o1 = Some a -> o2 = Some a. (* -------------------------------------------------------------------------- *) (* This lemma exploits an assertion of the form [less_defined (Some _) _]. *) Lemma invert_less_defined_Some: forall {A} {a : A} {o : option A}, less_defined (Some a) o -> Some a = o. Proof. unfold less_defined. intros. symmetry. eauto. Qed. Ltac invert_less_defined := match goal with | h: less_defined (Some _) _ |- _ => generalize (invert_less_defined_Some h); clear h; intro h end. (* -------------------------------------------------------------------------- *) (* These lemmas help prove assertions of the form [less_defined _ _]. *) Lemma prove_less_defined_None: forall {A} {o : option A}, less_defined None o. Proof. unfold less_defined. intros. congruence. Qed. Lemma reflexive_less_defined: forall {A} {o : option A}, less_defined o o. Proof. unfold less_defined. eauto. Qed. Local Hint Extern 1 (_ <> _) => congruence : congruence. Lemma prove_less_defined_bind: forall {A B} {f1 f2 : option A} {k1 k2 : A -> option B}, less_defined f1 f2 -> (f1 <> None -> forall a, less_defined (k1 a) (k2 a)) -> less_defined (f1 >>= k1) (f2 >>= k2). Proof. intros. destruct f1; simpl in *. (* Case: [f1] is [Some _]. *) { invert_less_defined. subst. simpl. eauto with congruence. } (* Case: [f1] is [None]. *) { eauto using prove_less_defined_None. } Qed. Hint Resolve prove_less_defined_None reflexive_less_defined prove_less_defined_bind : less_defined.