-- | This module provides straightforward tweaks to modify parts of the current
-- 'TxSkel' based on various kinds of optics.
module Cooked.Tweak.Update
  ( -- * Setting tweaks
    setTweak,
    isetTweak,

    -- * Overing tweaks
    overTweak,
    ioverTweak,

    -- * Traversing tweaks
    traverseTweak,
    itraverseTweak,
  )
where

import Cooked.Skeleton
import Cooked.Tweak.Common
import Optics.Core
import Polysemy

-- * Basic modifying 'Tweak's

-- | The tweak that sets a certain value in the 'TxSkel'.
setTweak ::
  (Member Tweak effs, Is k A_Setter) =>
  Optic' k is TxSkel a ->
  a ->
  Sem effs ()
setTweak :: forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Setter) =>
Optic' k is TxSkel a -> a -> Sem effs ()
setTweak Optic' k is TxSkel a
optic a
a = Sem effs TxSkel
forall (r :: EffectRow). Member Tweak r => Sem r TxSkel
getTxSkel Sem effs TxSkel -> (TxSkel -> Sem effs ()) -> Sem effs ()
forall (a :: OpticKind) (b :: OpticKind).
Sem effs a -> (a -> Sem effs b) -> Sem effs b
forall (m :: OpticKind -> OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Monad m =>
m a -> (a -> m b) -> m b
>>= TxSkel -> Sem effs ()
forall (r :: EffectRow). Member Tweak r => TxSkel -> Sem r ()
putTxSkel (TxSkel -> Sem effs ())
-> (TxSkel -> TxSkel) -> TxSkel -> Sem effs ()
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. Optic' k is TxSkel a -> a -> TxSkel -> TxSkel
forall (k :: OpticKind) (is :: IxList) (s :: OpticKind)
       (t :: OpticKind) (a :: OpticKind) (b :: OpticKind).
Is k A_Setter =>
Optic k is s t a b -> b -> s -> t
set Optic' k is TxSkel a
optic a
a

-- | Like 'setTweak', but the value to set is computed from the index of each
-- focus.
isetTweak ::
  (Member Tweak effs, Is k A_Setter) =>
  Optic' k (WithIx i) TxSkel a ->
  (i -> a) ->
  Sem effs ()
isetTweak :: forall (effs :: EffectRow) (k :: OpticKind) (i :: OpticKind)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Setter) =>
Optic' k (WithIx i) TxSkel a -> (i -> a) -> Sem effs ()
isetTweak Optic' k (WithIx i) TxSkel a
optic i -> a
f = Sem effs TxSkel
forall (r :: EffectRow). Member Tweak r => Sem r TxSkel
getTxSkel Sem effs TxSkel -> (TxSkel -> Sem effs ()) -> Sem effs ()
forall (a :: OpticKind) (b :: OpticKind).
Sem effs a -> (a -> Sem effs b) -> Sem effs b
forall (m :: OpticKind -> OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Monad m =>
m a -> (a -> m b) -> m b
>>= TxSkel -> Sem effs ()
forall (r :: EffectRow). Member Tweak r => TxSkel -> Sem r ()
putTxSkel (TxSkel -> Sem effs ())
-> (TxSkel -> TxSkel) -> TxSkel -> Sem effs ()
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. Optic' k (WithIx i) TxSkel a -> (i -> a) -> TxSkel -> TxSkel
forall (k :: OpticKind) (is :: IxList) (i :: OpticKind)
       (s :: OpticKind) (t :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
(Is k A_Setter, HasSingleIndex is i) =>
Optic k is s t a b -> (i -> b) -> s -> t
iset Optic' k (WithIx i) TxSkel a
optic i -> a
f

-- | The tweak that modifies a certain value in the 'TxSkel'.
overTweak ::
  (Member Tweak effs, Is k A_Setter) =>
  Optic k is TxSkel TxSkel a b ->
  (a -> b) ->
  Sem effs ()
overTweak :: forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind) (b :: OpticKind).
(Member Tweak effs, Is k A_Setter) =>
Optic k is TxSkel TxSkel a b -> (a -> b) -> Sem effs ()
overTweak Optic k is TxSkel TxSkel a b
optic a -> b
change = Sem effs TxSkel
forall (r :: EffectRow). Member Tweak r => Sem r TxSkel
getTxSkel Sem effs TxSkel -> (TxSkel -> Sem effs ()) -> Sem effs ()
forall (a :: OpticKind) (b :: OpticKind).
Sem effs a -> (a -> Sem effs b) -> Sem effs b
forall (m :: OpticKind -> OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Monad m =>
m a -> (a -> m b) -> m b
>>= TxSkel -> Sem effs ()
forall (r :: EffectRow). Member Tweak r => TxSkel -> Sem r ()
putTxSkel (TxSkel -> Sem effs ())
-> (TxSkel -> TxSkel) -> TxSkel -> Sem effs ()
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. Optic k is TxSkel TxSkel a b -> (a -> b) -> TxSkel -> TxSkel
forall (k :: OpticKind) (is :: IxList) (s :: OpticKind)
       (t :: OpticKind) (a :: OpticKind) (b :: OpticKind).
Is k A_Setter =>
Optic k is s t a b -> (a -> b) -> s -> t
over Optic k is TxSkel TxSkel a b
optic a -> b
change

-- | Like 'overTweak', but the modification of each focus also depends on its
-- index.
ioverTweak ::
  (Member Tweak effs, Is k A_Setter) =>
  Optic k (WithIx i) TxSkel TxSkel a b ->
  (i -> a -> b) ->
  Sem effs ()
ioverTweak :: forall (effs :: EffectRow) (k :: OpticKind) (i :: OpticKind)
       (a :: OpticKind) (b :: OpticKind).
(Member Tweak effs, Is k A_Setter) =>
Optic k (WithIx i) TxSkel TxSkel a b
-> (i -> a -> b) -> Sem effs ()
ioverTweak Optic k (WithIx i) TxSkel TxSkel a b
optic i -> a -> b
change = Sem effs TxSkel
forall (r :: EffectRow). Member Tweak r => Sem r TxSkel
getTxSkel Sem effs TxSkel -> (TxSkel -> Sem effs ()) -> Sem effs ()
forall (a :: OpticKind) (b :: OpticKind).
Sem effs a -> (a -> Sem effs b) -> Sem effs b
forall (m :: OpticKind -> OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Monad m =>
m a -> (a -> m b) -> m b
>>= TxSkel -> Sem effs ()
forall (r :: EffectRow). Member Tweak r => TxSkel -> Sem r ()
putTxSkel (TxSkel -> Sem effs ())
-> (TxSkel -> TxSkel) -> TxSkel -> Sem effs ()
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. Optic k (WithIx i) TxSkel TxSkel a b
-> (i -> a -> b) -> TxSkel -> TxSkel
forall (k :: OpticKind) (is :: IxList) (i :: OpticKind)
       (s :: OpticKind) (t :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
(Is k A_Setter, HasSingleIndex is i) =>
Optic k is s t a b -> (i -> a -> b) -> s -> t
iover Optic k (WithIx i) TxSkel TxSkel a b
optic i -> a -> b
change

-- | Like 'overTweak', but the modification of each focus runs in the tweak's
-- effect stack. The foci are visited in the order in which they occur in the
-- 'TxSkel'.
traverseTweak ::
  (Member Tweak effs, Is k A_Traversal) =>
  Optic' k is TxSkel a ->
  (a -> Sem effs a) ->
  Sem effs ()
traverseTweak :: forall (effs :: EffectRow) (k :: OpticKind) (is :: IxList)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Traversal) =>
Optic' k is TxSkel a -> (a -> Sem effs a) -> Sem effs ()
traverseTweak Optic' k is TxSkel a
optic a -> Sem effs a
change = Sem effs TxSkel
forall (r :: EffectRow). Member Tweak r => Sem r TxSkel
getTxSkel Sem effs TxSkel -> (TxSkel -> Sem effs TxSkel) -> Sem effs TxSkel
forall (a :: OpticKind) (b :: OpticKind).
Sem effs a -> (a -> Sem effs b) -> Sem effs b
forall (m :: OpticKind -> OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Monad m =>
m a -> (a -> m b) -> m b
>>= Optic' k is TxSkel a
-> (a -> Sem effs a) -> TxSkel -> Sem effs TxSkel
forall (k :: OpticKind) (f :: OpticKind -> OpticKind)
       (is :: IxList) (s :: OpticKind) (t :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
(Is k A_Traversal, Applicative f) =>
Optic k is s t a b -> (a -> f b) -> s -> f t
traverseOf Optic' k is TxSkel a
optic a -> Sem effs a
change Sem effs TxSkel -> (TxSkel -> Sem effs ()) -> Sem effs ()
forall (a :: OpticKind) (b :: OpticKind).
Sem effs a -> (a -> Sem effs b) -> Sem effs b
forall (m :: OpticKind -> OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Monad m =>
m a -> (a -> m b) -> m b
>>= TxSkel -> Sem effs ()
forall (r :: EffectRow). Member Tweak r => TxSkel -> Sem r ()
putTxSkel

-- | Like 'traverseTweak', for indexed optics
itraverseTweak ::
  (Member Tweak effs, Is k A_Traversal) =>
  Optic' k (WithIx is) TxSkel a ->
  (is -> a -> Sem effs a) ->
  Sem effs ()
itraverseTweak :: forall (effs :: EffectRow) (k :: OpticKind) (is :: OpticKind)
       (a :: OpticKind).
(Member Tweak effs, Is k A_Traversal) =>
Optic' k (WithIx is) TxSkel a
-> (is -> a -> Sem effs a) -> Sem effs ()
itraverseTweak Optic' k (WithIx is) TxSkel a
optic is -> a -> Sem effs a
change = Sem effs TxSkel
forall (r :: EffectRow). Member Tweak r => Sem r TxSkel
getTxSkel Sem effs TxSkel -> (TxSkel -> Sem effs TxSkel) -> Sem effs TxSkel
forall (a :: OpticKind) (b :: OpticKind).
Sem effs a -> (a -> Sem effs b) -> Sem effs b
forall (m :: OpticKind -> OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Monad m =>
m a -> (a -> m b) -> m b
>>= Optic' k (WithIx is) TxSkel a
-> (is -> a -> Sem effs a) -> TxSkel -> Sem effs TxSkel
forall (k :: OpticKind) (f :: OpticKind -> OpticKind)
       (is :: IxList) (i :: OpticKind) (s :: OpticKind) (t :: OpticKind)
       (a :: OpticKind) (b :: OpticKind).
(Is k A_Traversal, Applicative f, HasSingleIndex is i) =>
Optic k is s t a b -> (i -> a -> f b) -> s -> f t
itraverseOf Optic' k (WithIx is) TxSkel a
optic is -> a -> Sem effs a
change Sem effs TxSkel -> (TxSkel -> Sem effs ()) -> Sem effs ()
forall (a :: OpticKind) (b :: OpticKind).
Sem effs a -> (a -> Sem effs b) -> Sem effs b
forall (m :: OpticKind -> OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Monad m =>
m a -> (a -> m b) -> m b
>>= TxSkel -> Sem effs ()
forall (r :: EffectRow). Member Tweak r => TxSkel -> Sem r ()
putTxSkel