{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
module Internal.BuildPure
( PureBuilder
, createPure
) where
import Control.Monad.Catch (MonadThrow(..), SomeException)
import Control.Monad.Catch.Pure (CatchT, runCatchT)
import Control.Monad.Primitive (PrimMonad(..))
import Control.Monad.ST (ST)
import Control.Monad.Trans (MonadTrans(..))
import Data.Capnp.TraversalLimit (LimitT, MonadLimit, evalLimitT)
import Data.Mutable (Thaw(..), createT)
newtype PureBuilder s a = PureBuilder (LimitT (PrimCatchT (ST s)) a)
deriving(Functor, Applicative, Monad, MonadThrow, MonadLimit)
instance PrimMonad (PureBuilder s) where
type PrimState (PureBuilder s) = s
primitive = PureBuilder . primitive
runPureBuilder :: Int -> PureBuilder s a -> ST s (Either SomeException a)
runPureBuilder limit (PureBuilder m) = runPrimCatchT $ evalLimitT limit m
createPure :: Thaw a => Int -> (forall s. PureBuilder s (Mutable s a)) -> Either SomeException a
createPure limit m = createT (runPureBuilder limit m)
newtype PrimCatchT m a = PrimCatchT (CatchT m a)
deriving(Functor, Applicative, Monad, MonadThrow)
runPrimCatchT :: Monad m => PrimCatchT m a -> m (Either SomeException a)
runPrimCatchT (PrimCatchT m) = runCatchT m
instance MonadTrans PrimCatchT where
lift = PrimCatchT . lift
instance PrimMonad m => PrimMonad (PrimCatchT m) where
type PrimState (PrimCatchT m) = PrimState m
primitive = lift . primitive