{- |
Module      :  Network.Monad.Class
Copyright   :  (c) Henning Thielemann, 2009
License     :  BSD

Maintainer  :  http@henning-thielemann.de
Stability   :  experimental
Portability :  non-portable (not tested)


With this monad we abstract from the IO monad,
which also allows us to process data lazily or offline.
-}

{- How to use ByteString:
http://nominolo.blogspot.com/2007/05/networkhttp-bytestrings.html
-}
module Network.Monad.Transfer where

import qualified Network.Stream as Stream
import Control.Monad.Trans (MonadIO(liftIO), )
import Control.Monad (liftM, )

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

import Data.Monoid (Monoid)



type SyncExceptional m =
        Sync.ExceptionalT Stream.ConnError m

type AsyncExceptional m a =
        m (Async.Exceptional Stream.ConnError a)

data T m body =
   Cons {
      readLine   :: AsyncExceptional m body,
      readBlock  :: Int -> AsyncExceptional m body,
      writeBlock :: body -> SyncExceptional m ()
   }


liftIOSync :: MonadIO io =>
   IO (Stream.Result a) -> SyncExceptional io a
liftIOSync m =
   Sync.fromEitherT $ liftIO m

liftIOAsync :: (MonadIO io, Monoid a) =>
   IO (Stream.Result a) -> AsyncExceptional io a
liftIOAsync m =
   liftM (Async.fromSynchronousMonoid . Sync.fromEither) $
   liftIO m