content: {-# LANGUAGE AllowAmbiguousTypes         #-}
  {-# LANGUAGE ConstraintKinds             #-}
  
  module Polysemy.ConstraintAbsorber
    ( -- * Absorb builder
      absorbWithSem
  
      -- * Re-exports
    , Reifies
    , (:-) (Sub)
    , Dict (Dict)
    , reflect
    , Proxy (Proxy)
    ) where
  
  import           Data.Constraint (Dict(Dict), (:-)(Sub), (\\))
  import qualified Data.Constraint as C
  import qualified Data.Constraint.Unsafe as C
  import           Data.Kind (Type, Constraint)
  import           Data.Proxy (Proxy (..))
  import           Data.Reflection (Reifies, reflect)
  import qualified Data.Reflection as R
  import           Polysemy
  
  ------------------------------------------------------------------------------
  -- | This function can be used to locally introduce typeclass instances for
  -- 'Sem'. See 'Polysemy.ConstraintAbsorber.MonadState' for an example of how to
  -- use it.
  --
  -- @since 0.3.0.0
  absorbWithSem
      :: forall -- Constraint to be absorbed
                (p :: (Type -> Type) -> Constraint)
                -- Wrapper to avoid orphan instances
                (x :: (Type -> Type) -> Type -> Type -> Type)
                d r a
       . d  -- ^ Reified dictionary
      -> (forall s. R.Reifies s d :- p (x (Sem r) s))  -- ^ This parameter should always be @'Sub' 'Dict'@
      -> (p (Sem r) => Sem r a)
      -> Sem r a
  absorbWithSem d i m =  R.reify d $ \(_ :: Proxy (s :: Type)) -> m \\ C.trans
    (C.unsafeCoerceConstraint :: ((p (x m s) :- p m))) i
  {-# INLINEABLE absorbWithSem #-}
  
  