Section State.
Variable M : Type -> Type.
Variable S : Type.
Context {EQM : EqM M}.
Context {HM: Monad M}.
Context {HEQP: @EqMProps M _ EQM}.
Context {ML: @MonadLaws M _ HM}.
Global Instance EqM_stateTM : EqM (stateT S M).
Instance MonadLaws_stateTM : @MonadLaws (stateT S M) _ _.
Context {IM: Iter (Kleisli M) sum}.
Context {CM: Iterative (Kleisli M) sum}.
Definition iso {a b:Type} (sab : S * (a + b)) : (S * a) + (S * b) :=
match sab with
| (s, inl x) => inl (s, x)
| (s, inr y) => inr (s, y)
end.
Definition iso_inv {a b:Type} (sab : (S * a) + (S * b)) : S * (a + b) :=
match sab with
| inl (s, a) => (s, inl a)
| inr (s, b) => (s, inr b)
end.
Definition internalize {a b:Type} (f : Kleisli (stateT S M) a b) : Kleisli M (S * a) (S * b) :=
fun (sa : S * a) => f (snd sa) (fst sa).
Global Instance Iter_stateTM : Iter (Kleisli (stateT S M)) sum.
Global Instance IterUnfold_stateTM : IterUnfold (Kleisli (stateT S M)) sum.
Global Instance IterNatural_stateTM : IterNatural (Kleisli (stateT S M)) sum.

Lemma internalize_pure_iso {a b c} (f : Kleisli (stateT S M) a (b + c)) :
((internalize f) >>> pure iso) ⩯ (fun sa => (bind (f (snd sa) (fst sa))) (fun sbc => ret (iso sbc))).