hen-0.1.1: src/System/Xen/High/Internal.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE CPP #-}
module System.Xen.High.Internal
( XenT(..)
, Xen
, MonadXen(..)
, runXenT
) where
import Control.Applicative (Applicative)
import Control.Exception (SomeException)
import Data.Monoid (Monoid)
import Control.Monad.Catch (MonadCatch, try, bracket)
import Control.Monad.Reader (MonadReader(..), ReaderT, runReaderT, mapReaderT, ask)
import Control.Monad.RWS (MonadRWS)
import Control.Monad.State (MonadState(..))
import Control.Monad.Writer (MonadWriter(..))
import Control.Monad.Trans (MonadIO, MonadTrans(lift))
import Control.Monad.Trans.Identity (IdentityT(..))
import qualified Control.Monad.Cont as Cont
import qualified Control.Monad.Error as Error
import qualified Control.Monad.State.Lazy as LazyState
import qualified Control.Monad.State.Strict as StrictState
import qualified Control.Monad.Writer.Lazy as LazyWriter
import qualified Control.Monad.Writer.Strict as StrictWriter
import qualified Control.Monad.RWS.Lazy as LazyRWS
import qualified Control.Monad.RWS.Strict as StrictRWS
import System.Xen.Types (XcHandle)
import qualified System.Xen.Mid as Mid
------------------------------------------------------------------------------
-- * The mtl style typeclass
class (Functor m, MonadIO m) => MonadXen m where
-- | Helper function for creating high-level interface functions from mid-level.
-- Generally high-level function is just @highLevel = withXenHandle midLevel@.
withXenHandle :: (XcHandle -> m a) -> m a
instance MonadXen m => MonadXen (Cont.ContT r m) where
withXenHandle = Cont.mapContT id . withXenHandle
instance (MonadXen m, Error.Error e) => MonadXen (Error.ErrorT e m) where
withXenHandle = Error.mapErrorT id . withXenHandle
deriving instance MonadXen m => MonadXen (IdentityT m)
instance MonadXen m => MonadXen (LazyState.StateT s m) where
withXenHandle = LazyState.mapStateT id . withXenHandle
instance MonadXen m => MonadXen (StrictState.StateT s m) where
withXenHandle = StrictState.mapStateT id . withXenHandle
instance MonadXen m => MonadXen (ReaderT r m) where
withXenHandle = mapReaderT id . withXenHandle
instance (MonadXen m, Monoid w) => MonadXen (LazyWriter.WriterT w m) where
withXenHandle = LazyWriter.mapWriterT id . withXenHandle
instance (MonadXen m, Monoid w) => MonadXen (StrictWriter.WriterT w m) where
withXenHandle = StrictWriter.mapWriterT id . withXenHandle
instance (MonadXen m, Monoid w) => MonadXen (LazyRWS.RWST r w s m) where
withXenHandle = LazyRWS.mapRWST id . withXenHandle
instance (MonadXen m, Monoid w) => MonadXen (StrictRWS.RWST r w s m) where
withXenHandle = StrictRWS.mapRWST id . withXenHandle
-- * The @transformers@-style monad transfomer
------------------------------------------------------------------------------
-- | A Xen transformer. This transformers keeps connection to the Xen
-- hypervisor interface.
newtype XenT m a = XenT { unXenT :: ReaderT XcHandle m a }
deriving (Functor, Applicative, Monad, MonadTrans, MonadIO, MonadCatch)
-- | Most simple 'XenT' implementation.
type Xen = XenT IO
instance (Functor m, MonadIO m, MonadCatch m) => MonadXen (XenT m) where
withXenHandle f = f =<< XenT ask
instance MonadState s m => MonadState s (XenT m) where
get = lift get
put = lift . put
#if MIN_VERSION_mtl(2,1,0)
state = lift . state
#endif
instance MonadReader r m => MonadReader r (XenT m) where
ask = lift ask
local f = XenT . mapReaderT (local f) . unXenT
instance MonadWriter w m => MonadWriter w (XenT m) where
tell = lift . tell
listen = XenT . listen . unXenT
pass = XenT . pass . unXenT
instance MonadRWS r w s m => MonadRWS r w s (XenT m)
-- | Open new connection to the hypervisor, run any @Xen@ action and close
-- connection if nessesary. This function can fail with @Either SomeException@ with
-- 'System.Xen.Errors.XcHandleOpenError' and any error of providing @Xen@ action.
runXenT :: (Functor m, MonadIO m, MonadCatch m) => XenT m a -> m (Either SomeException a)
runXenT (XenT f) = try $ withNewHandle $ runReaderT f
where
withNewHandle = bracket Mid.interfaceOpen Mid.interfaceClose