-- |
-- 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 :: forall s i a. (s -> (i, a)) -> IxGetter i s a
ito s -> (i, a)
f = forall k (is :: IxList) s t a b.
(forall (p :: * -> * -> * -> *) i.
 Profunctor p =>
 Optic_ k p i (Curry is i) s t a b)
-> Optic k is s t a b
Optic (forall (p :: * -> * -> * -> *) a b i c.
Profunctor p =>
(a -> b) -> p i b c -> p i a c
lmap s -> (i, a)
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> * -> *) i a b s t j.
Strong p =>
(forall (f :: * -> *). Functor f => (i -> a -> f b) -> s -> f t)
-> p j a b -> p (i -> j) s t
ilinear forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> * -> *) i c a b.
(Profunctor p, Bicontravariant p) =>
p i c a -> p i c b
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 :: forall a. IxGetter a a a
selfIndex = forall s i a. (s -> (i, a)) -> IxGetter i s a
ito (\a
a -> (a
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 :: forall k (is :: IxList) i s a.
(Is k A_Getter, HasSingleIndex is i) =>
Optic' k is s a -> s -> (i, a)
iview Optic' k is s a
o = forall k (is :: IxList) i s a r.
(Is k A_Getter, HasSingleIndex is i) =>
Optic' k is s a -> (i -> a -> r) -> s -> r
iviews Optic' k is s a
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 :: forall k (is :: IxList) i s a r.
(Is k A_Getter, HasSingleIndex is i) =>
Optic' k is s a -> (i -> a -> r) -> s -> r
iviews Optic' k is s a
o = \i -> a -> r
f ->
  forall r i a b. IxForget r i a b -> i -> a -> r
runIxForget (forall (p :: * -> * -> * -> *) k (is :: IxList) s t a b i.
Profunctor p =>
Optic k is s t a b -> Optic_ k p i (Curry is i) s t a b
getOptic (forall destKind srcKind (is :: IxList) s t a b.
Is srcKind destKind =>
Optic srcKind is s t a b -> Optic destKind is s t a b
castOptic @A_Getter Optic' k is s a
o) (forall r i a b. (i -> a -> r) -> IxForget r i a b
IxForget i -> a -> r
f)) forall a. a -> a
id
{-# INLINE iviews #-}