{-# LANGUAGE BlockArguments #-}
module Cauldron.Managed
(
Managed,
managed,
with,
)
where
import Control.Concurrent.MVar
import Control.Exception.Base
import Control.Monad.Fix
import Control.Monad.IO.Class
import GHC.IO.Unsafe
newtype Managed a = Managed (forall b. (a -> IO b) -> IO b)
managed :: (forall r. (a -> IO r) -> IO r) -> Managed a
managed :: forall a. (forall r. (a -> IO r) -> IO r) -> Managed a
managed = (forall b. (a -> IO b) -> IO b) -> Managed a
forall a. (forall r. (a -> IO r) -> IO r) -> Managed a
Managed
instance MonadFix Managed where
mfix :: forall a. (a -> Managed a) -> Managed a
mfix a -> Managed a
f = (forall b. (a -> IO b) -> IO b) -> Managed a
forall a. (forall r. (a -> IO r) -> IO r) -> Managed a
Managed \a -> IO b
k -> do
m <- IO (MVar a)
forall a. IO (MVar a)
newEmptyMVar
x <-
unsafeDupableInterleaveIO
( readMVar m `catch` \BlockedIndefinitelyOnMVar
BlockedIndefinitelyOnMVar ->
FixIOException -> IO a
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO FixIOException
FixIOException
)
unManage (f x) \a
x' -> do
MVar a -> a -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar a
m a
x'
a -> IO b
k a
x'
where
unManage :: Managed a -> (a -> IO b) -> IO b
unManage (Managed forall b. (a -> IO b) -> IO b
a) = (a -> IO b) -> IO b
forall b. (a -> IO b) -> IO b
a
with :: Managed a -> (a -> IO b) -> IO b
with :: forall {a} {b}. Managed a -> (a -> IO b) -> IO b
with (Managed forall b. (a -> IO b) -> IO b
r) = (a -> IO b) -> IO b
forall b. (a -> IO b) -> IO b
r
instance Functor Managed where
fmap :: forall a b. (a -> b) -> Managed a -> Managed b
fmap a -> b
f (Managed forall b. (a -> IO b) -> IO b
m) = (forall b. (b -> IO b) -> IO b) -> Managed b
forall a. (forall r. (a -> IO r) -> IO r) -> Managed a
Managed (\b -> IO b
k -> (a -> IO b) -> IO b
forall b. (a -> IO b) -> IO b
m (\a
x -> b -> IO b
k (a -> b
f a
x)))
{-# INLINE fmap #-}
instance Applicative Managed where
pure :: forall a. a -> Managed a
pure a
x = (forall b. (a -> IO b) -> IO b) -> Managed a
forall a. (forall r. (a -> IO r) -> IO r) -> Managed a
Managed (\a -> IO b
k -> a -> IO b
k a
x)
{-# INLINE pure #-}
Managed forall b. ((a -> b) -> IO b) -> IO b
f <*> :: forall a b. Managed (a -> b) -> Managed a -> Managed b
<*> Managed forall b. (a -> IO b) -> IO b
g = (forall b. (b -> IO b) -> IO b) -> Managed b
forall a. (forall r. (a -> IO r) -> IO r) -> Managed a
Managed (\b -> IO b
bfr -> ((a -> b) -> IO b) -> IO b
forall b. ((a -> b) -> IO b) -> IO b
f (\a -> b
ab -> (a -> IO b) -> IO b
forall b. (a -> IO b) -> IO b
g (\a
x -> b -> IO b
bfr (a -> b
ab a
x))))
{-# INLINE (<*>) #-}
instance Monad Managed where
return :: forall a. a -> Managed a
return = a -> Managed a
forall a. a -> Managed a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
{-# INLINE return #-}
Managed a
m >>= :: forall a b. Managed a -> (a -> Managed b) -> Managed b
>>= a -> Managed b
k = (forall b. (b -> IO b) -> IO b) -> Managed b
forall a. (forall r. (a -> IO r) -> IO r) -> Managed a
Managed (\b -> IO b
c -> Managed a -> (a -> IO b) -> IO b
forall {a} {b}. Managed a -> (a -> IO b) -> IO b
with Managed a
m (\a
a -> Managed b -> (b -> IO b) -> IO b
forall {a} {b}. Managed a -> (a -> IO b) -> IO b
with (a -> Managed b
k a
a) b -> IO b
c))
{-# INLINE (>>=) #-}
instance MonadIO Managed where
liftIO :: forall a. IO a -> Managed a
liftIO IO a
m = (forall b. (a -> IO b) -> IO b) -> Managed a
forall a. (forall r. (a -> IO r) -> IO r) -> Managed a
Managed \a -> IO b
return_ -> do
a <- IO a
m
return_ a
{-# INLINE liftIO #-}