-- |
-- Module: Optics.State.Operators
-- Description: Infix operators for state-modifying optics.
--
-- Defines infix operators for the operations in "Optics.State".  These
-- operators are not exposed by the main @Optics@ module, but must be imported
-- explicitly.
--
module Optics.State.Operators (
  -- * State modifying optics
  (.=), (?=), (%=),
  -- * State modifying optics with passthrough
  (%%=),
  -- * Returning new value
  (<.=), (<?=), (<%=),
  -- * Returning old value
  (<<.=), (<<?=), (<<%=),
  -- * Passthrough
  PermeableOptic (..),
  ) where

import Control.Monad.State (MonadState)
import qualified Control.Monad.State as State

import Optics.Core
import Optics.Passthrough
import Optics.State
import Optics.View

infix 4 .=, ?=, %=

-- | Replace the target(s) of an 'Optic' in our monadic state with a new value,
-- irrespective of the old.
--
-- This is an infix version of 'assign'.
(.=)
  :: (Is k A_Setter, MonadState s m)
  => Optic k is s s a b
  -> b
  -> m ()
.= :: Optic k is s s a b -> b -> m ()
(.=) = Optic k is s s a b -> b -> m ()
forall (k :: OpticKind) (s :: OpticKind)
       (m :: OpticKind -> OpticKind) (is :: IxList) (a :: OpticKind)
       (b :: OpticKind).
(Is k A_Setter, MonadState s m) =>
Optic k is s s a b -> b -> m ()
assign
{-# INLINE (.=) #-}

-- | Replace the target(s) of an 'Optic' in our monadic state with 'Just' a new
-- value, irrespective of the old.
(?=)
  :: (Is k A_Setter, MonadState s m)
  => Optic k is s s (Maybe a) (Maybe b)
  -> b
  -> m ()
?= :: Optic k is s s (Maybe a) (Maybe b) -> b -> m ()
(?=) = \Optic k is s s (Maybe a) (Maybe b)
o -> Optic k is s s (Maybe a) (Maybe b) -> Maybe b -> m ()
forall (k :: OpticKind) (s :: OpticKind)
       (m :: OpticKind -> OpticKind) (is :: IxList) (a :: OpticKind)
       (b :: OpticKind).
(Is k A_Setter, MonadState s m) =>
Optic k is s s a b -> b -> m ()
assign Optic k is s s (Maybe a) (Maybe b)
o (Maybe b -> m ()) -> (b -> Maybe b) -> b -> m ()
forall (b :: OpticKind) (c :: OpticKind) (a :: OpticKind).
(b -> c) -> (a -> b) -> a -> c
. b -> Maybe b
forall (a :: OpticKind). a -> Maybe a
Just
{-# INLINE (?=) #-}

-- | Map over the target(s) of an 'Optic' in our monadic state.
--
-- This is an infix version of 'modifying'.
(%=)
  :: (Is k A_Setter, MonadState s m)
  => Optic k is s s a b
  -> (a -> b)
  -> m ()
%= :: Optic k is s s a b -> (a -> b) -> m ()
(%=) = Optic k is s s a b -> (a -> b) -> m ()
forall (k :: OpticKind) (s :: OpticKind)
       (m :: OpticKind -> OpticKind) (is :: IxList) (a :: OpticKind)
       (b :: OpticKind).
(Is k A_Setter, MonadState s m) =>
Optic k is s s a b -> (a -> b) -> m ()
modifying
{-# INLINE (%=) #-}

-------------------------------------------------------------------------------
-- Extra stuff
-------------------------------------------------------------------------------

-- | Modify the target of an 'PermeableOptic' in the current state returning
-- some extra information of type depending on the optic (@r@, @Maybe r@ or
-- monoidal summary).
infix 4 %%=
(%%=)
  :: (PermeableOptic k r, MonadState s m)
  => Optic k is s s a b
  -> (a -> (r, b))
  -> m (ViewResult k r)
Optic k is s s a b
o %%= :: Optic k is s s a b -> (a -> (r, b)) -> m (ViewResult k r)
%%= a -> (r, b)
f = (s -> (ViewResult k r, s)) -> m (ViewResult k r)
forall (s :: OpticKind) (m :: OpticKind -> OpticKind)
       (a :: OpticKind).
MonadState s m =>
(s -> (a, s)) -> m a
State.state (Optic k is s s a b -> (a -> (r, b)) -> s -> (ViewResult k r, s)
forall (k :: OpticKind) (r :: OpticKind) (is :: IxList)
       (s :: OpticKind) (t :: OpticKind) (a :: OpticKind)
       (b :: OpticKind).
PermeableOptic k r =>
Optic k is s t a b -> (a -> (r, b)) -> s -> (ViewResult k r, t)
passthrough Optic k is s s a b
o a -> (r, b)
f)
{-# INLINE (%%=) #-}

-------------------------------------------------------------------------------
-- Returning new value
-------------------------------------------------------------------------------

infix 4 <.=, <?=, <%=

-- | Modify the target of a 'PermeableOptic' into your 'Monad''s state by a user
-- supplied function and return the result.
(<%=)
  :: (PermeableOptic k b, MonadState s m)
  => Optic k is s s a b
  -> (a -> b)
  -> m (ViewResult k b)
Optic k is s s a b
o <%= :: Optic k is s s a b -> (a -> b) -> m (ViewResult k b)
<%= a -> b
f = Optic k is s s a b
o Optic k is s s a b -> (a -> (b, b)) -> m (ViewResult k b)
forall (k :: OpticKind) (r :: OpticKind) (s :: OpticKind)
       (m :: OpticKind -> OpticKind) (is :: IxList) (a :: OpticKind)
       (b :: OpticKind).
(PermeableOptic k r, MonadState s m) =>
Optic k is s s a b -> (a -> (r, b)) -> m (ViewResult k r)
%%= \a
a -> let b :: b
b = a -> b
f a
a in (b
b, b
b)
{-# INLINE (<%=) #-}

-- | Set 'Just' a value with pass-through.
--
-- This is useful for chaining assignment without round-tripping through your
-- 'Monad' stack.
(<?=)
  :: (PermeableOptic k (Maybe b), MonadState s m)
  => Optic k is s s (Maybe a) (Maybe b)
  -> b
  -> m (ViewResult k (Maybe b))
Optic k is s s (Maybe a) (Maybe b)
o <?= :: Optic k is s s (Maybe a) (Maybe b)
-> b -> m (ViewResult k (Maybe b))
<?= b
b = Optic k is s s (Maybe a) (Maybe b)
o Optic k is s s (Maybe a) (Maybe b)
-> Maybe b -> m (ViewResult k (Maybe b))
forall (k :: OpticKind) (b :: OpticKind) (s :: OpticKind)
       (m :: OpticKind -> OpticKind) (is :: IxList) (a :: OpticKind).
(PermeableOptic k b, MonadState s m) =>
Optic k is s s a b -> b -> m (ViewResult k b)
<.= b -> Maybe b
forall (a :: OpticKind). a -> Maybe a
Just b
b
{-# INLINE (<?=) #-}

-- | Set with pass-through.
--
-- This is useful for chaining assignment without round-tripping through your
-- 'Monad' stack.
(<.=)
  :: (PermeableOptic k b, MonadState s m)
  => Optic k is s s a b
  -> b
  -> m (ViewResult k b)
Optic k is s s a b
o <.= :: Optic k is s s a b -> b -> m (ViewResult k b)
<.= b
b = Optic k is s s a b
o Optic k is s s a b -> (a -> b) -> m (ViewResult k b)
forall (k :: OpticKind) (b :: OpticKind) (s :: OpticKind)
       (m :: OpticKind -> OpticKind) (is :: IxList) (a :: OpticKind).
(PermeableOptic k b, MonadState s m) =>
Optic k is s s a b -> (a -> b) -> m (ViewResult k b)
<%= b -> a -> b
forall (a :: OpticKind) (b :: OpticKind). a -> b -> a
const b
b
{-# INLINE (<.=) #-}

-------------------------------------------------------------------------------
-- Returning old value
-------------------------------------------------------------------------------

infix 4 <<.=, <<?=, <<%=

-- | Modify the target of a 'PermeableOptic' into your 'Monad''s state by a user
-- supplied function and return the /old/ value that was replaced.
(<<%=)
  :: (PermeableOptic k a, MonadState s m)
  => Optic k is s s a b
  -> (a -> b)
  -> m (ViewResult k a)
Optic k is s s a b
o <<%= :: Optic k is s s a b -> (a -> b) -> m (ViewResult k a)
<<%= a -> b
f = Optic k is s s a b
o Optic k is s s a b -> (a -> (a, b)) -> m (ViewResult k a)
forall (k :: OpticKind) (r :: OpticKind) (s :: OpticKind)
       (m :: OpticKind -> OpticKind) (is :: IxList) (a :: OpticKind)
       (b :: OpticKind).
(PermeableOptic k r, MonadState s m) =>
Optic k is s s a b -> (a -> (r, b)) -> m (ViewResult k r)
%%= \a
a -> (a
a, a -> b
f a
a)
{-# INLINE (<<%=) #-}

-- | Replace the target of a 'PermeableOptic' into your 'Monad''s state with
-- 'Just' a user supplied value and return the /old/ value that was replaced.
(<<?=)
  :: (PermeableOptic k (Maybe a), MonadState s m)
  => Optic k is s s (Maybe a) (Maybe b)
  -> b
  -> m (ViewResult k (Maybe a))
Optic k is s s (Maybe a) (Maybe b)
o <<?= :: Optic k is s s (Maybe a) (Maybe b)
-> b -> m (ViewResult k (Maybe a))
<<?= b
b = Optic k is s s (Maybe a) (Maybe b)
o Optic k is s s (Maybe a) (Maybe b)
-> Maybe b -> m (ViewResult k (Maybe a))
forall (k :: OpticKind) (a :: OpticKind) (s :: OpticKind)
       (m :: OpticKind -> OpticKind) (is :: IxList) (b :: OpticKind).
(PermeableOptic k a, MonadState s m) =>
Optic k is s s a b -> b -> m (ViewResult k a)
<<.= b -> Maybe b
forall (a :: OpticKind). a -> Maybe a
Just b
b
{-# INLINE (<<?=) #-}

-- | Replace the target of a 'PermeableOptic' into your 'Monad''s state with a
-- user supplied value and return the /old/ value that was replaced.
(<<.=)
  :: (PermeableOptic k a, MonadState s m)
  => Optic k is s s a b
  -> b
  -> m (ViewResult k a)
Optic k is s s a b
o <<.= :: Optic k is s s a b -> b -> m (ViewResult k a)
<<.= b
b = Optic k is s s a b
o Optic k is s s a b -> (a -> b) -> m (ViewResult k a)
forall (k :: OpticKind) (a :: OpticKind) (s :: OpticKind)
       (m :: OpticKind -> OpticKind) (is :: IxList) (b :: OpticKind).
(PermeableOptic k a, MonadState s m) =>
Optic k is s s a b -> (a -> b) -> m (ViewResult k a)
<<%= b -> a -> b
forall (a :: OpticKind) (b :: OpticKind). a -> b -> a
const b
b
{-# INLINE (<<.=) #-}