module Control.Quiver.Instances () where
import Control.Quiver.Internal
import Control.Monad.Catch
import Control.Monad.IO.Class (MonadIO (..))
import Data.IORef (newIORef, readIORef, writeIORef)
instance (MonadThrow f) => MonadThrow (P a a' b b' f) where
throwM = qlift . throwM
instance (MonadCatch f) => MonadCatch (P a a' b b' f) where
catch p onErr = go p
where
go p' = case p' of
Consume x k q -> consume x (go . k) (decouple (go q))
Produce y k q -> produce y (go . k) (deplete (go q))
Enclose m -> enclose (catch (go <$> m) (return . onErr))
Deliver r -> deliver r
instance (MonadIO f, MonadMask f) => MonadMask (P a a' b b' f) where
mask = liftMask mask
uninterruptibleMask = liftMask uninterruptibleMask
data Restore m = Unmasked | Masked (forall x . m x -> m x)
liftMask :: (MonadIO f, MonadMask f)
=> (forall s. ((forall x. f x -> f x) -> f s) -> f s)
-> ((forall x. P a a' b b' f x -> P a a' b b' f x)
-> P a a' b b' f r)
-> P a a' b b' f r
liftMask maskVariant pk = do
ioref <- liftIO $ newIORef Unmasked
let
maskM p = case p of
Consume x k q -> consume x (maskM . k) (decouple (maskM q))
Produce y k q -> produce y (maskM . k) (deplete (maskM q))
Enclose m -> enclose $ maskVariant $ \unmaskVariant -> do
liftIO $ writeIORef ioref $ Masked unmaskVariant
maskM <$> (m >>= mergeAdjacent)
Deliver r -> deliver r
unmask p = case p of
Consume x k q -> consume x (unmask . k) (decouple (unmask q))
Produce y k q -> produce y (unmask . k) (deplete (unmask q))
Enclose m -> enclose $ do
Masked unmaskVariant <- liftIO $ readIORef ioref
unmaskVariant (unmask <$> (m >>= mergeAdjacent))
Deliver r -> deliver r
mergeAdjacent p = case p of
Enclose m -> m >>= mergeAdjacent
_ -> return p
maskM (pk unmask)