{-# LANGUAGE ConstraintKinds            #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Network.Livy.Monad
  ( 
    Livy
  , LivyT (..)
  , LivyConstraint
  , runLivy
  , runLivyT
  ) where
import Control.Lens
import Control.Monad.Catch
import Control.Monad.Reader
import Control.Monad.Trans.Resource
import Data.Aeson
import Network.Livy.Env
import Network.Livy.Types
type Livy = LivyT Env (ResourceT IO)
runLivy :: HasEnv r => r -> Livy a -> IO a
runLivy e = runResourceT . runLivyT (e ^. environment)
newtype LivyT r m a = LivyT { unLivyT :: ReaderT r m a }
  deriving ( Applicative, Functor, Monad
           , MonadTrans, MonadIO, MonadReader r
           , MonadThrow, MonadCatch, MonadResource
           )
runLivyT :: HasEnv r => r -> LivyT r m a -> m a
runLivyT r (LivyT m) = runReaderT m r
type LivyConstraint r m a =
  ( HasEnv r, MonadIO m, MonadThrow m, MonadCatch m
  , MonadReader r m, LivyRequest a, FromJSON (LivyResponse a)
  )