Some Type Magic

Mutable references to keep track of the registered release actions. You might think we could just use a StateT transformer, but then our state wouldn't survive exceptions.

transformer, but then our state wouldn't survive exceptions. We only want to register actions in the base monad . For example, if we have a ResourceT (WriterT [Int] IO) stack, we only want to register IO actions. This makes it easy to lift our stacks around (i.e., add an extra transformer to the middle of an existing stack), and avoids confusing issues about the threading of other monadic side-effects.

. For example, if we have a stack, we only want to register actions. This makes it easy to lift our stacks around (i.e., add an extra transformer to the middle of an existing stack), and avoids confusing issues about the threading of other monadic side-effects. Some way to guarantee an action is performed, even in the presence of exceptions. This boils down to needing a bracket -like function.

class Monad m => HasRef m where type Ref m :: * -> * newRef' :: a -> m ( Ref m a) readRef' :: Ref m a -> m a writeRef' :: Ref m a -> a -> m () modifyRef' :: Ref m a -> (a -> (a, b)) -> m b mask :: ((forall a. m a -> m a) -> m b) -> m b mask_ :: m a -> m a try :: m a -> m ( Either SomeException a)

instance HasRef IO where type Ref IO = I.IORef newRef' = I. newIORef modifyRef' = I. atomicModifyIORef readRef' = I. readIORef writeRef' = I. writeIORef mask = E. mask mask_ = E. mask_ try = E. try

class ( HasRef ( Base m), Monad m) => Resource m where type Base m :: * -> * resourceLiftBase :: Base m a -> m a

resourceBracket_ :: Base m a -> Base m b -> m c -> m c

instance Resource IO where type Base IO = IO resourceLiftBase = id resourceBracket_ = E. bracket_