content: {-# LANGUAGE CPP #-}
  {-# LANGUAGE RankNTypes #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  
  -- | Functions from "Control.Exception.Lens", but using 'MonadUnliftIO', not
  -- 'MonadCatch'
  module UnliftIO.Exception.Lens
    ( catching
    , catching_
    , handling
    , handling_
    , trying
    , trying_
    ) where
  
  import Prelude
  
  import Control.Monad.IO.Unlift (MonadUnliftIO)
  import Control.Monad (liftM)
  import Data.Monoid (First)
  import UnliftIO.Exception (SomeException, catchJust, tryJust)
  import Control.Applicative (Const(..))
  import Data.Monoid (First(..))
  
  #if __GLASGOW_HASKELL__ >= 708
  import Data.Coerce
  #else
  import Unsafe.Coerce
  #endif
  
  -- | 'Control.Exception.Lens.catching' using 'MonadUnliftIO'
  --
  -- @since 0.2.25.0
  catching :: MonadUnliftIO m => Getting (First a) SomeException a -> m r -> (a -> m r) -> m r
  catching l = catchJust (preview l)
  {-# INLINE catching #-}
  
  -- | 'Control.Exception.Lens.catching_' using 'MonadUnliftIO'
  --
  -- @since 0.2.25.0
  catching_ :: MonadUnliftIO m => Getting (First a) SomeException a -> m r -> m r -> m r
  catching_ l a b = catchJust (preview l) a (const b)
  {-# INLINE catching_ #-}
  
  -- | 'Control.Exception.Lens.handling' using 'MonadUnliftIO'
  --
  -- @since 0.2.25.0
  handling :: MonadUnliftIO m => Getting (First a) SomeException a -> (a -> m r) -> m r -> m r
  handling l = flip (catching l)
  {-# INLINE handling #-}
  
  -- | 'Control.Exception.Lens.handling_' using 'MonadUnliftIO'
  --
  -- @since 0.2.25.0
  handling_ :: MonadUnliftIO m => Getting (First a) SomeException a -> m r -> m r -> m r
  handling_ l = flip (catching_ l)
  {-# INLINE handling_ #-}
  
  -- | 'Control.Exception.Lens.trying' using 'MonadUnliftIO'
  --
  -- @since 0.2.25.0
  trying :: MonadUnliftIO m => Getting (First a) SomeException a -> m r -> m (Either a r)
  trying l = tryJust (preview l)
  {-# INLINE trying #-}
  
  -- | 'Control.Exception.Lens.trying_' using 'MonadUnliftIO'
  --
  -- @since 0.2.25.0
  trying_ :: MonadUnliftIO m => Getting (First a) SomeException a -> m r -> m (Maybe r)
  trying_ l m = preview _Right `liftM` trying l m
  {-# INLINE trying_ #-}
  
  --------------------------------------------------------------------------------
  -- Enough of (micro)lens to accomplish this mondule without any dependencies
  --
  -- TODO: code review note: should we just bring in microlens?
  --------------------------------------------------------------------------------
  type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t
  
  _Right :: Traversal (Either a b) (Either a b') b b'
  _Right f (Right b) = Right <$> f b
  _Right _ (Left a) = pure (Left a)
  {-# INLINE _Right #-}
  
  type Getting r s a = (a -> Const r a) -> s -> Const r s
  
  preview :: Getting (First a) s a -> s -> Maybe a
  preview l = getFirst #. foldMapOf l (First #. Just)
  {-# INLINE preview #-}
  
  foldMapOf :: Getting r s a -> (a -> r) -> s -> r
  foldMapOf l f = getConst #. l (Const #. f)
  {-# INLINE foldMapOf #-}
  
  #if __GLASGOW_HASKELL__ >= 708
  ( #. ) :: Coercible c b => (b -> c) -> (a -> b) -> (a -> c)
  ( #. ) _ = coerce (\x -> x :: b) :: forall a b. Coercible b a => a -> b
  #else
  ( #. ) :: (b -> c) -> (a -> b) -> (a -> c)
  ( #. ) _ = unsafeCoerce
  #endif
  
  {-# INLINE ( #. ) #-}
  
  infixr 9 #.
  