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