-- |
-- 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 :: (s -> (i, a)) -> IxGetter i s a
ito s -> (i, a)
f = (forall (p :: * -> * -> * -> *) i.
 Profunctor p =>
 Optic_ A_Getter p i (Curry (WithIx i) i) s s a a)
-> IxGetter i s a
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 ((s -> (i, a)) -> p (i -> i) (i, a) s -> p (i -> i) s s
forall (p :: * -> * -> * -> *) a b i c.
Profunctor p =>
(a -> b) -> p i b c -> p i a c
lmap s -> (i, a)
f (p (i -> i) (i, a) s -> p (i -> i) s s)
-> (p i a a -> p (i -> i) (i, a) s) -> p i a a -> p (i -> i) s s
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall (f :: * -> *).
 Functor f =>
 (i -> a -> f s) -> (i, a) -> f s)
-> p i a s -> p (i -> i) (i, a) s
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
forall (f :: * -> *). Functor f => (i -> a -> f s) -> (i, a) -> f s
uncurry' (p i a s -> p (i -> i) (i, a) s)
-> (p i a a -> p i a s) -> p i a a -> p (i -> i) (i, a) s
forall b c a. (b -> c) -> (a -> b) -> a -> c
. p i a a -> p i a s
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 :: IxGetter a a a
selfIndex = (a -> (a, a)) -> IxGetter a a a
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 :: Optic' k is s a -> s -> (i, a)
iview Optic' k is s a
o = Optic' k is s a -> (i -> a -> (i, a)) -> s -> (i, a)
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 :: Optic' k is s a -> (i -> a -> r) -> s -> r
iviews Optic' k is s a
o = \i -> a -> r
f ->
  IxForget r (i -> i) s s -> (i -> i) -> s -> r
forall r i a b. IxForget r i a b -> i -> a -> r
runIxForget (Optic A_Getter is s s a a
-> Optic__ (IxForget r) i (Curry is i) s s a a
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 (Optic' k is s a -> Optic A_Getter is s s a a
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) ((i -> a -> r) -> IxForget r i a a
forall r i a b. (i -> a -> r) -> IxForget r i a b
IxForget i -> a -> r
f)) i -> i
forall a. a -> a
id
{-# INLINE iviews #-}