{-# LANGUAGE RankNTypes #-}
module Notmuch.Util where
import Control.Exception (bracket)
import Control.Monad.Except (MonadError, ExceptT, runExceptT, throwError)
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad.Reader (MonadReader, asks)
import Data.Foldable (traverse_)
import Data.Functor.Identity (Identity(..))
import Data.Profunctor (Choice)
import Data.Profunctor.Unsafe ((#.), (.#))
import Data.Tagged (Tagged(..))
type Prism s t a b = forall p f. (Choice p, Applicative f) => p a (f b) -> p s (f t)
type Prism' s a = Prism s s a a
type Lens' a b = forall f. Functor f => (b -> f b) -> (a -> f a)
review :: MonadReader b m => Prism' t b -> m t
review p = asks (runIdentity #. unTagged #. p .# Tagged .# Identity)
{-# INLINE review #-}
bracketT
:: (MonadError e m, MonadIO m)
=> ExceptT e IO a
-> (a -> ExceptT e IO b)
-> (a -> ExceptT e IO c)
-> m c
bracketT acq rel go = liftIO (
bracket
(runExceptT acq)
(runExceptT . traverse_ rel)
(runExceptT . either throwError go)
) >>= either throwError pure