{-# LANGUAGE Rank2Types #-} module Graphics.FreeGame.Internal.Resource (ResourceT(..), finalizer, runResourceT) where import Control.Monad.IO.Class import Control.Applicative newtype ResourceT m a = ResourceT { unResourceT :: forall r. (a -> m r) -> (IO () -> r -> m r) -> m r } finalizer :: Monad m => IO () -> ResourceT m () finalizer m = ResourceT $ \p f -> p () >>= f m instance Functor (ResourceT m) where fmap f (ResourceT g) = ResourceT $ \p -> g (p . f) instance Applicative (ResourceT m) where pure a = ResourceT $ \p _ -> p a ResourceT ff <*> ResourceT fa = ResourceT $ \p f -> ff (\a -> fa (\b -> p (a b)) f) f instance Monad (ResourceT m) where return a = ResourceT $ \p _ -> p a ResourceT rf >>= k = ResourceT $ \p f -> rf (\x -> unResourceT (k x) p f) f instance MonadIO m => MonadIO (ResourceT m) where liftIO m = ResourceT $ \r _ -> liftIO m >>= r runResourceT :: MonadIO m => ResourceT m a -> m a runResourceT (ResourceT z) = do (fin, a) <- z (\a -> return (return (), a)) (\m (fs, r) -> return (m >> fs, r)) liftIO fin return a