optics-core-0.1: src/Optics/IxSetter.hs
{-# LANGUAGE DataKinds #-}
-- |
-- Module: Optics.IxSetter
-- Description: An indexed version of an 'Optics.Setter.Setter'.
--
-- An 'IxSetter' is an indexed version of an 'Optics.Setter.Setter'. 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.IxSetter
(
-- * Formation
IxSetter
, IxSetter'
-- * Introduction
, isets
-- * Elimination
, iover
-- * Computation
-- |
--
-- @
-- 'iover' ('isets' f) ≡ f
-- @
-- * Well-formedness
-- |
--
-- * __PutPut__: Setting twice is the same as setting once:
--
-- @
-- 'Optics.Setter.iset' l v' ('Optics.Setter.iset' l v s) ≡ 'Optics.Setter.iset' l v' s
-- @
--
-- * __Functoriality__: 'IxSetter's must preserve identities and composition:
--
-- @
-- 'iover' s ('const' 'id') ≡ 'id'
-- 'iover' s f '.' 'iover' s g ≡ 'iover' s (\i -> f i '.' g i)
-- @
-- * Additional introduction forms
, imapped
-- * Additional elimination forms
, iset
, iset'
, iover'
-- * Subtyping
, A_Setter
-- * Re-exports
, FunctorWithIndex(..)
) where
import Optics.Internal.Indexed
import Optics.Internal.IxSetter
import Optics.Internal.Optic
import Optics.Internal.Profunctor
-- | Type synonym for a type-modifying indexed setter.
type IxSetter i s t a b = Optic A_Setter (WithIx i) s t a b
-- | Type synonym for a type-preserving indexed setter.
type IxSetter' i s a = Optic' A_Setter (WithIx i) s a
-- | Apply an indexed setter as a modifier.
iover
:: (Is k A_Setter, is `HasSingleIndex` i)
=> Optic k is s t a b
-> (i -> a -> b) -> s -> t
iover o = \f -> runIxFunArrow (getOptic (castOptic @A_Setter o) (IxFunArrow f)) id
{-# INLINE iover #-}
-- | Apply an indexed setter as a modifier, strictly.
iover'
:: (Is k A_Setter, is `HasSingleIndex` i)
=> Optic k is s t a b
-> (i -> a -> b) -> s -> t
iover' o = \f ->
let star = getOptic (castOptic @A_Setter o) $ IxStar (\i -> wrapIdentity' . f i)
in unwrapIdentity' . runIxStar star id
{-# INLINE iover' #-}
-- | Apply an indexed setter.
--
-- @
-- 'iset' o f ≡ 'iover' o (\i _ -> f i)
-- @
--
iset
:: (Is k A_Setter, is `HasSingleIndex` i)
=> Optic k is s t a b
-> (i -> b) -> s -> t
iset o = \f -> iover o (\i _ -> f i)
{-# INLINE iset #-}
-- | Apply an indexed setter, strictly.
iset'
:: (Is k A_Setter, is `HasSingleIndex` i)
=> Optic k is s t a b
-> (i -> b) -> s -> t
iset' o = \f -> iover' o (\i _ -> f i)
{-# INLINE iset' #-}
-- | Build an indexed setter from a function to modify the element(s).
isets
:: ((i -> a -> b) -> s -> t)
-> IxSetter i s t a b
isets f = Optic (iroam f)
{-# INLINE isets #-}
-- | Indexed setter via the 'FunctorWithIndex' class.
--
-- @
-- 'iover' 'imapped' ≡ 'imap'
-- @
imapped :: FunctorWithIndex i f => IxSetter i (f a) (f b) a b
imapped = Optic imapped__
{-# INLINE imapped #-}