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).
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).