module RIO where import Prelude hiding (read) {-@ data FIO a
 Prop, post :: World -> a -> World -> Prop> 
  = FIO (rs :: (x:World
 -> (a, World)<\w -> {v:World | true}>))
  @-}
data FIO a  = FIO {runState :: World -> (a, World)}

{-@ runState :: forall 
 Prop, post :: World -> a -> World -> Prop>. 
                FIO  a -> x:World
 -> (a, World)<\w -> {v:World | true}> @-}

data World  = W


-- | forall m k v k'. sel (upd m k v) k' = if (k == k') then v else sel m k'

{-@ measure sel :: World -> FilePath -> Int          @-}
{-@ measure upd :: World -> FilePath -> Int -> World @-}


{-@ open :: fp:FilePath -> FIO <{\w0 -> true}, {\w0 r w1 -> w1 = w0  && sel w0 fp = 1}> () @-}
open :: FilePath -> FIO () 
open = undefined

{-@ read :: fp:FilePath -> FIO <{\w0 -> sel w0 fp = 1}, {\w0 r w1 -> w1 = w0}> String @-}
read :: FilePath -> FIO String
read = undefined

--------------------------


{-@
bind :: forall < pre   :: World -> Prop 
               , pre2  :: World -> Prop 
               , p     :: a -> Prop
               , post1 :: World -> a -> World -> Prop
               , post2 :: World -> b -> World -> Prop
               , post :: World -> b -> World -> Prop>.
       {w:World
 -> x:a -> World -> World}        
       {w:World
 -> y:a -> w2:World -> x:b -> World -> World}        
       FIO  a
    -> (a -> FIO  b)
    -> FIO  b 

  @-}
bind :: FIO a -> (a -> FIO b) -> FIO b
bind (FIO g) f = FIO (\x -> case g x of {(y, s) -> (runState (f y)) s})    


-- is the precondition true or p?
{-@ ret :: forall 

Prop>. x:a -> FIO w0 == w1 && y == x }> a @-} ret :: a -> FIO a ret w = FIO $ \x -> (w, x) ok1 f = open f {-@ fail1 :: FilePath -> FIO String @-} fail1 :: FilePath -> FIO String fail1 f = read f ok2 f = open f `bind` \_ -> read f instance Monad FIO where {-@ instance Monad FIO where >>= :: forall < pre :: World -> Prop , pre2 :: World -> Prop , p :: a -> Prop , post1 :: World -> a -> World -> Prop , post2 :: World -> b -> World -> Prop , post :: World -> b -> World -> Prop>. {w:World

 -> x:a -> World -> World}        
       {w:World
 -> y:a -> w2:World -> x:b -> World -> World}        
       FIO  a
    -> (a -> FIO  b)
    -> FIO  b ;
 >>  :: forall < pre   :: World -> Prop 
               , pre2  :: World -> Prop 
               , p     :: a -> Prop
               , post1 :: World -> a -> World -> Prop
               , post2 :: World -> b -> World -> Prop
               , post :: World -> b -> World -> Prop>.
       {w:World
 -> x:a -> World -> World}        
       {w:World
 -> y:a -> w2:World -> x:b -> World -> World}        
       FIO  a
    -> FIO  b
    -> FIO  b ;
 return :: forall 

Prop>. x:a -> FIO w0 == w1 && y == x }> a @-} (FIO g) >>= f = FIO $ \x -> case g x of {(y, s) -> (runState (f y)) s} (FIO g) >> f = FIO $ \x -> case g x of {(y, s) -> (runState f ) s} return w = FIO $ \x -> (w, x) fail = error {-@ ok3 :: FilePath -> FIO String @-} ok3 f = do open f read f