content: -- |
  -- Module: Optics.Coerce
  -- Description: Operators to 'coerce' the type parameters of 'Optic'.
  --
  -- This module defines operations to 'coerce' the type parameters of optics to
  -- a representationally equal type.  For example, if we have
  --
  -- > newtype MkInt = MkInt Int
  --
  -- and
  --
  -- > l :: Lens' S Int
  --
  -- then
  --
  -- > coerceA @Int @MkInt l :: Lens' S MkInt
  --
  module Optics.Coerce
    ( coerceS
    , coerceT
    , coerceA
    , coerceB
    ) where
  
  import Data.Coerce
  
  import Data.Profunctor.Indexed
  
  import Optics.Internal.Optic
  
  -- | Lift 'coerce' to the @s@ parameter of an optic.
  coerceS
    :: Coercible s s'
    => Optic k is s  t a b
    -> Optic k is s' t a b
  coerceS = \(Optic o) -> Optic (lcoerce . o)
  {-# INLINE coerceS #-}
  
  -- | Lift 'coerce' to the @t@ parameter of an optic.
  coerceT
    :: Coercible t t'
    => Optic k is s t  a b
    -> Optic k is s t' a b
  coerceT = \(Optic o) -> Optic (rcoerce . o)
  {-# INLINE coerceT #-}
  
  -- | Lift 'coerce' to the @a@ parameter of an optic.
  coerceA
    :: Coercible a a'
    => Optic k is s t a  b
    -> Optic k is s t a' b
  coerceA = \(Optic o) -> Optic (o . lcoerce)
  {-# INLINE coerceA #-}
  
  -- | Lift 'coerce' to the @b@ parameter of an optic.
  coerceB
    :: Coercible b b'
    => Optic k is s t a b
    -> Optic k is s t a b'
  coerceB = \(Optic o) -> Optic (o . rcoerce)
  {-# INLINE coerceB #-}
  