Definition State S X := S -> X * S.Definition ret {S X} : X -> State S X := pair.Definition bind {S X Y} : State S X ->
  (X -> State S Y) -> State S Y :=
  fun m f s => let (x, s') := m s in f x s'.Definition get {S} : State S S :=
  fun s => (s, s).Definition put {S} : S -> State S unit :=
  fun s _ => (tt, s).Definition state_lift {S X} (Pre Post : S -> Prop)
  (P : X -> Prop) : State S X -> Prop :=
  fun f => forall s, Pre s ->
    P (fst (f s)) /\ Post (snd (f s)).

(* Specifications: *)
Lemma weaken_lemma {S X} {Pre : S -> Prop} (Post : S -> Prop) {Post' : S -> Prop} (P : X -> Prop) {P' : X -> Prop} (m : State S X) : (forall s, Post s -> Post' s) -> (forall x, P x -> P' x) -> state_lift Pre Post P m -> state_lift Pre Post' P' m.
Lemma ret_lemma {S X} {Pre : S -> Prop} {P : X -> Prop} {x : X} : P x -> state_lift 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 : State S X} {f : X -> State S Y} : state_lift Pre Mid P mx -> (forall x, P x -> state_lift Mid Post Q (f x)) -> state_lift Pre Post Q (bind mx f).
Lemma get_lemma {S} {Pre : S -> Prop} : state_lift Pre Pre Pre get.
Lemma put_lemma {S} {Pre Pre' : S -> Prop} {s : S} : Pre' s -> state_lift 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 : State S X) : (forall s, Post s -> Post' s) -> (forall x, P x -> P' x) -> state_lift Pre Post P m -> state_lift Pre Post' P' m.
Lemma ret_lemma {S X} {Pre : S -> Prop} {P : X -> Prop} {x : X} : P x -> state_lift 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 : State S X} {f : X -> State S Y} : state_lift Pre Mid P mx -> (forall x, P x -> state_lift Mid Post Q (f x)) -> state_lift Pre Post Q (bind mx f).
Lemma get_lemma {S} {Pre : S -> Prop} : state_lift Pre Pre Pre get.
Lemma put_lemma {S} {Pre Pre' : S -> Prop} {s : S} : Pre' s -> state_lift Pre Pre' (fun _ => True) (put s).