packages feed

liquidhaskell-0.8.0.2: tests/todo/EffSTT.hs

module EffSTT (

  -- * Basic STT type and instances
    STT
  , Ptr
    
  -- * Monadic operators
  , ret
  , bind

  -- * Create a reference
  , newPtr
 
  -- * Read a reference
  , readPtr

  -- * Write a reference
  , writePtr
    
  )where

import qualified Data.Map as M

type State  = M.Map Int Int
newtype Ptr = Ptr Int
data STT a  = STT (State -> (a, State)) 

----------------------------------------------------------------
-- | Accessing State via Ptr
----------------------------------------------------------------

{-@ newPtr :: forall <H :: HProp>.
                 n:Int
              -> STT <{H}, {\l -> H * l := n}> Ptr
  @-} 
newPtr   :: Int -> STT Ptr
newPtr n = STT $ \m0 ->
  let p  = M.size m0
      m1 = M.insert p n m0
  in
      (Ptr p, m1)

{-@ readPtr :: forall <p :: Int -> Prop, H :: HProp>.
                  l:Ptr
               -> STT <{H * l := Int<p>}, {\_ -> H * l := Int<p>}> Int<p>
  @-}
readPtr         :: Ptr -> STT Int
readPtr (Ptr p) = STT $ \m0 ->
  (M.findWithDefault (error "readPtr DIES") p m0, m0)


{-@ writePtr :: forall <p :: Int -> Prop, H :: HProp>.
                   l:Ptr
                -> Int<p>
                -> STT <{H * l := Int}, {\_ -> H * l := Int<p>}> () 
  @-} 
writePtr :: Ptr -> Int -> STT () 
writePtr (Ptr p) n = STT $ \m0 ->
  ((), M.insert p n m0)

----------------------------------------------------------------
-- | Monad instance for STT
----------------------------------------------------------------

instance Monad STT where
  return = ret
  (>>=)  = bind

ret   :: a -> STT a
ret x = STT (\s0 -> (x, s0))

bind :: STT a -> (a -> STT b) -> STT b
bind (STT f) k = STT $ \s0 ->
  let (x, s1) = f s0
      STT fk  = k x
  in
      fk s1

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