Library ASCommon.CResult
The point of this module is to keep the sum type symmetric and use this to
assign a meaning to success and error (and a corresponding monad instance)
The naming is intended to match Ocaml's result as Haskell uses Either which
is similar to the regular sum.
The error type is first so that result E is a monad
Context {E A : Type}.
Inductive result : Type :=
| Ok (val : A)
| Error (err : E).
Definition get_Ok (r : result) : option A :=
match r with
| Ok val ⇒ Some val
| Error err ⇒ None
end.
Definition get_Error (r : result) : option E :=
match r with
| Ok val ⇒ None
| Error err ⇒ Some err
end.
Inductive result : Type :=
| Ok (val : A)
| Error (err : E).
Definition get_Ok (r : result) : option A :=
match r with
| Ok val ⇒ Some val
| Error err ⇒ None
end.
Definition get_Error (r : result) : option E :=
match r with
| Ok val ⇒ None
| Error err ⇒ Some err
end.
Takes an option but convert None into the provided error
Definition res_from_opt (e : E) : option A → result :=
from_option Ok (Error e).
Definition res_to_opt := get_Ok.
Definition res_from_suml (s : A + E) : result :=
match s with
| inl val ⇒ Ok val
| inr err ⇒ Error err
end.
Definition res_from_sumr (s : E + A) : result :=
match s with
| inr val ⇒ Ok val
| inl err ⇒ Error err
end.
Definition res_to_suml (r : result) : A + E :=
match r with
| Ok val ⇒ inl val
| Error err ⇒ inr err
end.
Definition res_to_sumr (r : result) : E + A :=
match r with
| Ok val ⇒ inr val
| Error err ⇒ inl err
end.
Lemma res_from_to_suml (s : A + E) : res_to_suml (res_from_suml s) = s.
Proof using. by destruct s. Qed.
Lemma res_to_from_suml (r : result) : res_from_suml (res_to_suml r) = r.
Proof using. by destruct r. Qed.
Lemma res_from_to_sumr (s : E + A) : res_to_sumr (res_from_sumr s) = s.
Proof using. by destruct s. Qed.
Lemma res_to_from_sumr (r : result) : res_from_sumr (res_to_sumr r) = r.
Proof using. by destruct r. Qed.
from_option Ok (Error e).
Definition res_to_opt := get_Ok.
Definition res_from_suml (s : A + E) : result :=
match s with
| inl val ⇒ Ok val
| inr err ⇒ Error err
end.
Definition res_from_sumr (s : E + A) : result :=
match s with
| inr val ⇒ Ok val
| inl err ⇒ Error err
end.
Definition res_to_suml (r : result) : A + E :=
match r with
| Ok val ⇒ inl val
| Error err ⇒ inr err
end.
Definition res_to_sumr (r : result) : E + A :=
match r with
| Ok val ⇒ inr val
| Error err ⇒ inl err
end.
Lemma res_from_to_suml (s : A + E) : res_to_suml (res_from_suml s) = s.
Proof using. by destruct s. Qed.
Lemma res_to_from_suml (r : result) : res_from_suml (res_to_suml r) = r.
Proof using. by destruct r. Qed.
Lemma res_from_to_sumr (s : E + A) : res_to_sumr (res_from_sumr s) = s.
Proof using. by destruct s. Qed.
Lemma res_to_from_sumr (r : result) : res_from_sumr (res_to_sumr r) = r.
Proof using. by destruct r. Qed.
is_Err and is_Ret are doing the same as is_Some but for results
Definition is_Error (r : result) := ∃ err, r = Error err.
#[export] Instance is_Error_Decision (r : result) : Decision (is_Error r).
Proof.
refine (match r with | Error _ ⇒ left _ | _ ⇒ right _ end);
unfold is_Error;
naive_solver.
Defined.
Definition is_Ok (r : result) := ∃ val, r = Ok val.
#[export] Instance is_Ok_Decision (r : result) : Decision (is_Ok r).
Proof.
refine (match r with | Ok _ ⇒ left _ | _ ⇒ right _ end);
unfold is_Ok;
naive_solver.
Defined.
#[export] Instance cdestruct_is_Ok r :
CDestrSimpl false (is_Ok r) (∃ o, r = Ok o).
Proof. tcclean. now unfold is_Ok. Qed.
#[export] Instance obv_true_is_Ok_Ok x : ObvTrue (is_Ok (Ok x)).
Proof. tcclean. unfold is_Ok. eauto. Qed.
#[export] Instance obv_false_is_Ok_Error x : ObvFalse (is_Ok (Error x)).
Proof. tcclean. unfold is_Ok. naive_solver. Qed.
#[export] Instance is_Error_Decision (r : result) : Decision (is_Error r).
Proof.
refine (match r with | Error _ ⇒ left _ | _ ⇒ right _ end);
unfold is_Error;
naive_solver.
Defined.
Definition is_Ok (r : result) := ∃ val, r = Ok val.
#[export] Instance is_Ok_Decision (r : result) : Decision (is_Ok r).
Proof.
refine (match r with | Ok _ ⇒ left _ | _ ⇒ right _ end);
unfold is_Ok;
naive_solver.
Defined.
#[export] Instance cdestruct_is_Ok r :
CDestrSimpl false (is_Ok r) (∃ o, r = Ok o).
Proof. tcclean. now unfold is_Ok. Qed.
#[export] Instance obv_true_is_Ok_Ok x : ObvTrue (is_Ok (Ok x)).
Proof. tcclean. unfold is_Ok. eauto. Qed.
#[export] Instance obv_false_is_Ok_Error x : ObvFalse (is_Ok (Error x)).
Proof. tcclean. unfold is_Ok. naive_solver. Qed.
Unpack a result into any monad that supports that error type
Definition unpack_result `{MThrow E M, MRet M} (r : result) : M A :=
match r with
| Ok val ⇒ mret val
| Error err ⇒ mthrow err
end.
#[export] Instance result_eq_dec `{EqDecision E} `{EqDecision A} : EqDecision (result).
Proof. solve_decision. Defined.
End Result.
Arguments result : clear implicits.
Instance DecisionT_result `{DecisionT E} `{DecisionT A} : DecisionT (result E A).
Proof. sfirstorder. Qed.
Instance result_inhabited_ok {E} `{Inhabited A} : Inhabited (result E A).
Proof. firstorder. Defined.
Instance result_inhabited_error `{Inhabited E} {A} : Inhabited (result E A).
Proof. firstorder. Defined.
match r with
| Ok val ⇒ mret val
| Error err ⇒ mthrow err
end.
#[export] Instance result_eq_dec `{EqDecision E} `{EqDecision A} : EqDecision (result).
Proof. solve_decision. Defined.
End Result.
Arguments result : clear implicits.
Instance DecisionT_result `{DecisionT E} `{DecisionT A} : DecisionT (result E A).
Proof. sfirstorder. Qed.
Instance result_inhabited_ok {E} `{Inhabited A} : Inhabited (result E A).
Proof. firstorder. Defined.
Instance result_inhabited_error `{Inhabited E} {A} : Inhabited (result E A).
Proof. firstorder. Defined.
Section ResultMonad.
Context {E : Type}.
#[export] Instance result_ret : MRet (result E) := @Ok E.
#[export] Instance result_throw : MThrow E (result E) := @Error E.
#[export] Instance result_bind : MBind (result E) :=
λ _ _ f r,
match r with
| Ok val ⇒ f val
| Error err ⇒ Error err
end.
#[export] Instance result_join : MJoin (result E) :=
λ _ r,
match r with
| Error err ⇒ Error err
| Ok (Error err) ⇒ Error err
| Ok (Ok a) ⇒ Ok a
end.
#[export] Instance result_fmap : FMap (result E) :=
λ _ _ f r,
match r with
| Ok val ⇒ Ok (f val)
| Error err ⇒ Error err
end.
#[export] Instance result_monad : Monad (result E).
Proof. split; cdestruct |- *** ## cdestruct_result. Qed.
#[export] Instance result_monad_fmap : MonadFMap (result E).
Proof. cdestruct |- *** ## cdestruct_result. Qed.
End ResultMonad.
Context {E : Type}.
#[export] Instance result_ret : MRet (result E) := @Ok E.
#[export] Instance result_throw : MThrow E (result E) := @Error E.
#[export] Instance result_bind : MBind (result E) :=
λ _ _ f r,
match r with
| Ok val ⇒ f val
| Error err ⇒ Error err
end.
#[export] Instance result_join : MJoin (result E) :=
λ _ r,
match r with
| Error err ⇒ Error err
| Ok (Error err) ⇒ Error err
| Ok (Ok a) ⇒ Ok a
end.
#[export] Instance result_fmap : FMap (result E) :=
λ _ _ f r,
match r with
| Ok val ⇒ Ok (f val)
| Error err ⇒ Error err
end.
#[export] Instance result_monad : Monad (result E).
Proof. split; cdestruct |- *** ## cdestruct_result. Qed.
#[export] Instance result_monad_fmap : MonadFMap (result E).
Proof. cdestruct |- *** ## cdestruct_result. Qed.
End ResultMonad.