{-# LANGUAGE GeneralizedNewtypeDeriving , TypeFamilies , FlexibleInstances , MultiParamTypeClasses , UndecidableInstances , DeriveDataTypeable #-} module AWS.EC2.Class ( EC2 , runEC2 , ResponseParserException(..) , EC2Context(..) ) where import Control.Monad.State (StateT(..), MonadState) import qualified Control.Monad.State as S import Control.Applicative import Control.Monad (liftM) import Control.Monad.Base (MonadBase) import Control.Monad.IO.Class (MonadIO) import Control.Monad.Trans.Class (MonadTrans, lift) import Control.Monad.Trans.Control ( MonadBaseControl(..) , MonadTransControl(..) , ComposeSt , defaultLiftBaseWith , defaultRestoreM ) import Control.Exception (Exception) import Data.Typeable (Typeable) import qualified Network.HTTP.Conduit as HTTP import Data.Text (Text) import AWS.Types import AWS.Credential data EC2Context = EC2Context { manager :: HTTP.Manager , credential :: Credential , endpoint :: EC2Endpoint , lastRequestId :: Maybe Text } data ResponseParserException = NextToken Text deriving (Show, Typeable) instance Exception ResponseParserException newtype EC2 m a = EC2T { runEC2T :: StateT EC2Context m a } deriving ( Monad , Applicative , Functor , MonadIO , MonadState EC2Context , MonadBase base ) instance MonadTrans EC2 where lift = EC2T . lift instance MonadTransControl EC2 where newtype StT EC2 a = StEC2 { unStEC2 :: (a, EC2Context) } liftWith f = EC2T . StateT $ \s -> liftM (\x -> (x, s)) (f $ \a -> liftM StEC2 (S.runStateT (runEC2T a) s)) restoreT = EC2T . StateT . const . liftM unStEC2 instance MonadBaseControl base m => MonadBaseControl base (EC2 m) where newtype StM (EC2 m) a = StMEC2 { unStMEC2 :: ComposeSt EC2 m a } liftBaseWith = defaultLiftBaseWith StMEC2 restoreM = defaultRestoreM unStMEC2 runEC2 :: Monad m => EC2Context -> EC2 m a -> m a runEC2 ctx app = S.evalStateT (runEC2T app) ctx