content: -- |
  -- Module: Optics.IxGetter
  -- Description: An indexed version of a 'Optics.Getter.Getter'.
  --
  -- An 'IxGetter' is an indexed version of a 'Optics.Getter.Getter'. See the
  -- "Indexed optics" section of the overview documentation in the @Optics@ module
  -- of the main @optics@ package for more details on indexed optics.
  --
  module Optics.IxGetter
    (
    -- * Formation
      IxGetter
  
    -- * Introduction
    , ito
    , selfIndex
  
    -- * Elimination
    , iview
    , iviews
  
    -- * Subtyping
    , A_Getter
    ) where
  
  import Data.Profunctor.Indexed
  
  import Optics.Internal.Bi
  import Optics.Internal.Indexed
  import Optics.Internal.Optic
  import Optics.Internal.Utils
  
  -- | Type synonym for an indexed getter.
  type IxGetter i s a = Optic' A_Getter (WithIx i) s a
  
  -- | Build an indexed getter from a function.
  --
  -- >>> iview (ito id) ('i', 'x')
  -- ('i','x')
  ito :: (s -> (i, a)) -> IxGetter i s a
  ito f = Optic (lmap f . ilinear uncurry' . rphantom)
  {-# INLINE ito #-}
  
  -- | Use a value itself as its own index. This is essentially an indexed version
  -- of 'Optics.Iso.equality'.
  selfIndex :: IxGetter a a a
  selfIndex = ito (\a -> (a, a))
  {-# INLINE selfIndex #-}
  
  -- | View the value pointed to by an indexed getter.
  iview
    :: (Is k A_Getter, is `HasSingleIndex` i)
    => Optic' k is s a -> s -> (i, a)
  iview o = iviews o (,)
  {-# INLINE iview #-}
  
  -- | View the function of the value pointed to by an indexed getter.
  iviews
    :: (Is k A_Getter,  is `HasSingleIndex` i)
    => Optic' k is s a -> (i -> a -> r) -> s -> r
  iviews o = \f ->
    runIxForget (getOptic (castOptic @A_Getter o) (IxForget f)) id
  {-# INLINE iviews #-}
  