{- |
Provide the explicit class dictionary as context via a Reader monad.
-}
module Network.Monad.Reader where

import qualified Network.Monad.Transfer as Transfer

import qualified Network.Stream as Stream
import Control.Monad.Trans.Reader (ReaderT, asks, )
import Control.Monad.Trans.Class (lift, )

import qualified Control.Monad.Exception.Asynchronous as Async
import qualified Control.Monad.Exception.Synchronous  as Sync



type T body m = ReaderT (Transfer.T m body) m

type SyncExceptional body m =
   Sync.ExceptionalT Stream.ConnError (T body m)

type AsyncExceptional body m =
   Async.ExceptionalT Stream.ConnError (T body m)


{-# INLINE readLine #-}
readLine :: (Monad m) => AsyncExceptional body m body
readLine =
   Async.ExceptionalT $
   do action <- asks Transfer.readLine
      lift $ Async.runExceptionalT action

{-# INLINE readBlock #-}
readBlock :: (Monad m) => Int -> AsyncExceptional body m body
readBlock n =
   Async.ExceptionalT $
   do action <- asks Transfer.readBlock
      lift $ Async.runExceptionalT $ action n

{-# INLINE writeBlock #-}
writeBlock :: (Monad m) => body -> SyncExceptional body m ()
writeBlock body =
   do action <- lift $ asks Transfer.writeBlock
      Sync.mapExceptionalT lift $ action body