{-# LANGUAGE TypeOperators #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE DataKinds #-} module Data.Apiary.Extension ( Has(getExtension) , MonadExts(..), getExt , Middleware' , Extension(..) , Extensions , noExtension -- * initializer constructor , Initializer, initializer , Initializer', initializer' , initializerBracket , initializerBracket' -- * combine initializer , (+>) ) where import Control.Monad(liftM) import Data.Apiary.Extension.Internal(Has, getExtension, Initializer(Initializer)) import Control.Monad.Apiary.Action.Internal (MonadExts(getExts), Extension(..), Extensions(AddExtension), Middleware') getExt :: (MonadExts es m, Has e es) => proxy e -> m e getExt p = getExtension p `liftM` getExts type Initializer' m a = forall i. Initializer m i (a ': i) addExtension :: Extension e => e -> Extensions es -> Extensions (e ': es) addExtension = AddExtension initializer :: (Extension e, Monad m) => (Extensions es -> m e) -> Initializer m es (e ': es) initializer m = Initializer $ \es n -> do e <- m es n (addExtension e es) initializer' :: (Extension e, Monad m) => m e -> Initializer' m e initializer' m = initializer (const m) initializerBracket :: Extension e => (forall a. Extensions es -> (e -> m a) -> m a) -> Initializer m es (e ': es) initializerBracket b = Initializer $ \es n -> b es $ \e -> n (addExtension e es) initializerBracket' :: Extension e => (forall a. (e -> m a) -> m a) -> Initializer m es (e ': es) initializerBracket' m = initializerBracket (const m) -- | combine two Initializer. since 0.16.0. (+>) :: Monad m => Initializer m i x -> Initializer m x o -> Initializer m i o Initializer a +> Initializer b = Initializer $ \e m -> a e (\e' -> b e' m) noExtension :: Monad m => Initializer m i i noExtension = Initializer $ \es n -> n es