Section OptStateMonad.
Definition OptState S X := S -> option (X * S).
Definition ret {S X} : X -> OptState S X :=
fun x s => Some (x, s).
Definition bind {S X Y} : OptState S X ->
(X -> OptState S Y) -> OptState S Y :=
fun m f s =>
match m s with
| Some (x, s') => f x s'
| None => None
end.
Definition get {S} : OptState S S :=
fun s => Some (s, s).
Definition put {S} : S -> OptState S unit :=
fun s _ => Some (tt, s).
Definition opt_lift {X} (P : X -> Prop) : option X -> Prop :=
fun o =>
match o with
| Some x => P x
| None => True
end.
Definition opt_lift2 {X Y} (P : X -> Y -> Prop) : option X -> option Y -> Prop :=
fun o1 o2 =>
opt_lift (fun x => opt_lift (P x) o2) o1.
Definition opt_state_plift {S X}
(Pre Post : S -> Prop)
(P : X -> Prop) : OptState S X -> Prop :=
fun f => forall s, Pre s ->
opt_lift (fun p => P (fst p) /\ Post (snd p)) (f s).

(* Specifications: *)
Lemma weaken_lemma {S X}
{Pre : S -> Prop}
(Post : S -> Prop)
{Post' : S -> Prop}
(P : X -> Prop)
{P' : X -> Prop}
(m : OptState S X) :
(forall s, Post s -> Post' s) ->
(forall x, P x -> P' x) ->
opt_state_plift Pre Post P m ->
opt_state_plift Pre Post' P' m.
Lemma ret_lemma {S X}
{Pre : S -> Prop}
{P : X -> Prop}
{x : X} :
P x ->
opt_state_plift Pre Pre P (ret x).
Lemma bind_lemma {S X Y}
{Pre : S -> Prop}
(Mid : S -> Prop)
{Post : S -> Prop}
(P : X -> Prop)
{Q : Y -> Prop}
{mx : OptState S X}
{f : X -> OptState S Y} :
opt_state_plift Pre Mid P mx ->
(forall x, P x -> opt_state_plift Mid Post Q (f x)) ->
opt_state_plift Pre Post Q (bind mx f).
Lemma get_lemma {S}
{Pre : S -> Prop} :
opt_state_plift Pre Pre Pre get.
Lemma put_lemma {S}
{Pre Pre' : S -> Prop}
{s : S} :
Pre' s ->
opt_state_plift Pre Pre' (fun _ => True) (put s).