module Compose where




data ST s a = ST {runState :: s -> s}

{-@ data ST s a <p :: s -> Prop, q :: s -> s -> Prop> = ST (runState :: x:s<p> -> s<q x>) @-}




{-@ 
cmp :: forall < pref :: s -> Prop, postf :: s -> s -> Prop
              , pre  :: s -> Prop, postg :: s -> s -> Prop
              , post :: s -> s -> Prop
              >. 
       {y:s -> s<postg y> -> s<pref>}
       {x:s<pre> -> z:s<postg x> -> s<postf z> -> s<post x> }
       f:(ST <pref, postf> s a)
    -> g:(ST <pre , postg> s b)
    ->   (ST <pre , post > s b)
@-}

cmp :: ST s a
    -> ST s b
    -> ST s b

cmp (ST f) (ST g) = ST $ \s -> f (g s)


{-@ incr :: ST <{\x -> x >= 0}, {\x v -> v = x + 1}> Nat Int @-}
incr :: ST Int Int 
incr = ST $ \x -> x + 1

{-@ incr2 :: ST <{\x -> x >= 0}, {\x v -> v = x + 4}> Nat Int @-}
incr2 :: ST Int Int 
incr2 = cmp incr incr