module Compose where data ST s a = ST {runState :: s -> (a,s)} {-@ data ST s a

Prop, q :: s -> s -> Prop, r :: s -> a -> Prop> = ST (runState :: x:s

-> (a, s)) @-} {-@ runState :: forall

Prop, q :: s -> s -> Prop, r :: s -> a -> Prop>. ST s a -> x:s

-> (a, s) @-} {- cmp :: forall < pref :: s -> Prop, postf :: s -> s -> Prop , pre :: s -> Prop, postg :: s -> s -> Prop , post :: s -> s -> Prop , rg :: s -> a -> Prop , rf :: s -> b -> Prop , r :: s -> b -> Prop >. {xx:s

 -> w:s -> s -> s}
       {ww:s
 -> s -> s}
       (ST  s a)
    -> (ST  s b)
    -> (ST  s b)
@-}

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

cmp (ST g) (ST f) = ST (\x -> case g x of {(_, s) -> f s})    

{-@ 
bind :: forall < pref :: s -> Prop, postf :: s -> s -> Prop
              , pre  :: s -> Prop, postg :: s -> s -> Prop
              , post :: s -> s -> Prop
              , rg   :: s -> a -> Prop
              , rf   :: s -> b -> Prop
              , r    :: s -> b -> Prop
              , pref0 :: a -> Prop 
              >. 
       {x:s
 -> a -> a}      
       {x:s
 -> y:s -> b -> b}
       {xx:s
 -> w:s -> s -> s}
       {ww:s
 -> s -> s}
       (ST  s a)
    -> (a -> ST  s b)
    -> (ST  s b)
@-}

bind :: (ST s a)
    -> (a -> ST s b)
    -> (ST s b)

bind (ST g) f = ST (\x -> case g x of {(y, s) -> (runState (f y)) s})    


{-@ unit :: forall s a 

Prop>. x:a -> ST v == s}, {\s v -> x == v}> s a @-} unit :: a -> ST s a unit x = ST $ \s -> (x, s) {-@ incr :: ST <{\x -> x >= 0}, {\x v -> v = x + 1}, {\x v -> v = x}> Nat Nat @-} incr :: ST Int Int incr = ST $ \x -> (x, x + 1) {-@ incr' :: ST <{\x -> x >= 0}, {\x v -> v = x + 1}, {\w vw -> vw = w}> Nat Nat @-} incr' :: ST Int Int incr' = bind incr (\x -> unit x)