content: {-+
  An IO wrapper monad for redirecting Stdio.
  -}
  module SIO(SIO,StdIOops(..),runSIO,withStdio,inBase) where
  import Prelude hiding (getContents,readFile,writeFile,ioError,catch,putStr)
  import AbstractIO as A
  import EnvMT as E
  import MT(HasBaseMonad(..),HasEnv(..),Z)
  import MUtils
  
  newtype SIO a = SIO (WithEnv StdIOops IO a)
                deriving (Functor,Monad,FileIO,SystemIO,DirectoryIO,TimeIO)
  
  data StdIOops = StdIO {put,eput::String->IO (){-, get::IO String-}}
  
  runSIO (SIO m) = withEnv stdIOops m
    where stdIOops = StdIO { put=putStr,eput=ePutStr{-,get=getContents-}}
  
  withStdio ops = E.inEnv (ops::StdIOops)
  
  instance HasEnv SIO Z StdIOops where
    getEnv ix = SIO E.getEnv 
    inEnv _ e (SIO m) = SIO (E.inEnv e m)
  
  --instance HasBaseMonad IO IO where inBase = id
  
  instance HasBaseMonad SIO IO where
    inBase io = SIO $ lift io
  
  stdPut s = do put <- put # E.getEnv
  	      inBase (put s)
  stdePut s = do put <- eput # E.getEnv
  	       inBase (put s)
  {-
  stdGet = do get <- get # E.getEnv
  	    inBase get
  -}
  
  instance StdIO SIO where
    putStr = stdPut
    ePutStr = stdePut
    getContents = inBase getContents
  
  instance CatchIO IOError SIO where
    SIO m1 `catch` em2 = 
       SIO $
       m1 `catch` \ e ->
       let SIO m2 = em2 e
       in m2
    ioError = SIO . ioError
  
  instance CatchIO err m => CatchIO err (WithEnv e m) where
    m `catch` f = do e <- E.getEnv
                     lift (withEnv e m `catch` (withEnv e . f))
    ioError = lift . ioError
  