{-# LANGUAGE Rank2Types #-}
-- | Lenses allow you to use fields of the state of a state monad as if they were variables in an imperative language.
-- 'use' is used to retrieve the value of a variable, and '.=' and '%=' allow you to set and modify a variable.
-- C-style compound assignments are also provided.
module Lens.Family2.State.Strict
  ( LFS.zoom
  , use, uses
  , (%=)
  , assign, (.=)
  , (%%=)
  , (<~)
-- * Compound Assignments
  , (+=), (-=), (*=)
  , (//=)
  , (&&=), (||=)
  , (<>=)
-- * Strict Assignments
  , (%!=)
  , (+!=), (-!=), (*!=)
  , (//!=)
  , (&&!=), (||!=)
  , (<>!=)
-- * Types
  , LFS.Zooming
-- * Re-exports
  , LensLike, LensLike'
  , FoldLike, Constant
  , Setter, Setter', Identical
  , LFS.StateT, MonadState, Writer
  ) where

import Data.Tuple (swap)
import Control.Monad (liftM)
import Control.Monad.Trans.Writer.Lazy (Writer, writer, runWriter)
import Control.Monad.State.Strict (MonadState, get, modify, modify', state)
import Lens.Family2
import qualified Lens.Family.State.Strict as LFS

use :: MonadState s m => FoldLike a s t a b -> m a
-- ^ @
-- use :: MonadState s m => Getter s t a b -> m a
-- @
--
-- Retrieve a field of the state
--
-- @
-- use :: (MonadState s m, Monoid a) => Fold s t a b -> m a
-- @
--
-- Retrieve a monoidal summary of all the referenced fields from the state
use :: FoldLike a s t a b -> m a
use FoldLike a s t a b
l = FoldLike a s t a b -> s -> a
forall a s t b. FoldLike a s t a b -> s -> a
view FoldLike a s t a b
l (s -> a) -> m s -> m a
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` m s
forall s (m :: * -> *). MonadState s m => m s
get

uses :: MonadState s m => FoldLike r s t a b -> (a -> r) -> m r
-- ^ @
-- uses :: (MonadState s m, Monoid r) => Fold s t a b -> (a -> r) -> m r
-- @
--
-- Retrieve all the referenced fields from the state and foldMap the results together with @f :: a -> r@.
--
-- @
-- uses :: MonadState s m => Getter s t a b -> (a -> r) -> m r
-- @
--
-- Retrieve a field of the state and pass it through the function @f :: a -> r@.
--
-- @uses l f = f \<$> use l@
uses :: FoldLike r s t a b -> (a -> r) -> m r
uses FoldLike r s t a b
l a -> r
f = FoldLike r s t a b -> (a -> r) -> s -> r
forall r s t a b. FoldLike r s t a b -> (a -> r) -> s -> r
views FoldLike r s t a b
l a -> r
f (s -> r) -> m s -> m r
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` m s
forall s (m :: * -> *). MonadState s m => m s
get

infix 4 %=

-- | Modify a field of the state.
(%=) :: MonadState s m => Setter s s a b -> (a -> b) -> m ()
Setter s s a b
l %= :: Setter s s a b -> (a -> b) -> m ()
%= a -> b
f = (s -> s) -> m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (Setter s s a b
l Setter s s a b -> (a -> b) -> s -> s
forall s t a b. Setter s t a b -> (a -> b) -> s -> t
%~ a -> b
f)

infix 4 .=

-- | Set a field of the state.
(.=) :: MonadState s m => Setter s s a b -> b -> m ()
Setter s s a b
l .= :: Setter s s a b -> b -> m ()
.= b
v = Setter s s a b
l Setter s s a b -> (a -> b) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%= b -> a -> b
forall a b. a -> b -> a
const b
v

-- | Set a field of the state.
assign :: MonadState s m => Setter s s a b -> b -> m ()
assign :: Setter s s a b -> b -> m ()
assign = Setter s s a b -> b -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> b -> m ()
(.=)

infixr 2 <~

-- | Set a field of the state using the result of executing a stateful command.
(<~) :: MonadState s m => Setter s s a b -> m b -> m ()
Setter s s a b
l <~ :: Setter s s a b -> m b -> m ()
<~ m b
v = Setter s s a b -> b -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> b -> m ()
assign Setter s s a b
l (b -> m ()) -> m b -> m ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< m b
v

infix 4 %%=

(%%=) :: MonadState s m => LensLike (Writer c) s s a b -> (a -> (c, b)) -> m c
-- ^ @
-- (%%=) :: MonadState s m => Lens s s a b -> (a -> (c, b)) -> m c
-- @
--
-- Modify a field of the state while returning another value.
--
-- @
-- (%%=) :: (MonadState s m, Monoid c) => Traversal s s a b -> (a -> (c, b)) -> m c
-- @
--
-- Modify each field of the state and return the 'mconcat' of the other values.
LensLike (Writer c) s s a b
l %%= :: LensLike (Writer c) s s a b -> (a -> (c, b)) -> m c
%%= a -> (c, b)
f = (s -> (c, s)) -> m c
forall s (m :: * -> *) a. MonadState s m => (s -> (a, s)) -> m a
state ((s, c) -> (c, s)
forall a b. (a, b) -> (b, a)
swap ((s, c) -> (c, s)) -> (s -> (s, c)) -> s -> (c, s)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Writer c s -> (s, c)
forall w a. Writer w a -> (a, w)
runWriter (Writer c s -> (s, c)) -> (s -> Writer c s) -> s -> (s, c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LensLike (Writer c) s s a b
l ((b, c) -> WriterT c Identity b
forall (m :: * -> *) a w. Monad m => (a, w) -> WriterT w m a
writer ((b, c) -> WriterT c Identity b)
-> (a -> (b, c)) -> a -> WriterT c Identity b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (c, b) -> (b, c)
forall a b. (a, b) -> (b, a)
swap ((c, b) -> (b, c)) -> (a -> (c, b)) -> a -> (b, c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> (c, b)
f))

infixr 4 +=, -=, *=

(+=), (-=), (*=) :: (MonadState s m, Num a) => Setter' s a -> a -> m ()
Setter' s a
l += :: Setter' s a -> a -> m ()
+= a
a = Setter' s a
l Setter' s a -> (a -> a) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%= (a -> a -> a
forall a. Num a => a -> a -> a
+ a
a)
Setter' s a
l -= :: Setter' s a -> a -> m ()
-= a
a = Setter' s a
l Setter' s a -> (a -> a) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%= a -> a -> a
forall a. Num a => a -> a -> a
subtract a
a
Setter' s a
l *= :: Setter' s a -> a -> m ()
*= a
a = Setter' s a
l Setter' s a -> (a -> a) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%= (a -> a -> a
forall a. Num a => a -> a -> a
* a
a)

infixr 4 //=

(//=) :: (MonadState s m, Fractional a) => Setter' s a -> a -> m ()
Setter' s a
l //= :: Setter' s a -> a -> m ()
//= a
a = Setter' s a
l Setter' s a -> (a -> a) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%= (a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
a)

infixr 4 &&=, ||=

(&&=), (||=) :: MonadState s m => Setter' s Bool -> Bool -> m ()
Setter' s Bool
l &&= :: Setter' s Bool -> Bool -> m ()
&&= Bool
a = Setter' s Bool
l Setter' s Bool -> (Bool -> Bool) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%= (Bool -> Bool -> Bool
&& Bool
a)
Setter' s Bool
l ||= :: Setter' s Bool -> Bool -> m ()
||= Bool
a = Setter' s Bool
l Setter' s Bool -> (Bool -> Bool) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%= (Bool -> Bool -> Bool
|| Bool
a)

infixr 4 <>=

-- | Monoidally append a value to all referenced fields of the state.
(<>=) :: (MonadState s m, Monoid a) => Setter' s a -> a -> m ()
Setter' s a
l <>= :: Setter' s a -> a -> m ()
<>= a
a = Setter' s a
l Setter' s a -> (a -> a) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%= (a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
a)

infix 4 %!=

-- | Strictly modify a field of the state.
(%!=) :: MonadState s m => Setter s s a b -> (a -> b) -> m ()
Setter s s a b
l %!= :: Setter s s a b -> (a -> b) -> m ()
%!= a -> b
f = (s -> s) -> m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify' (Setter s s a b
l Setter s s a b -> (a -> b) -> s -> s
forall s t a b. Setter s t a b -> (a -> b) -> s -> t
%~ a -> b
f)

infixr 4 +!=, -!=, *!=

(+!=), (-!=), (*!=) :: (MonadState s m, Num a) => Setter' s a -> a -> m ()
Setter' s a
l +!= :: Setter' s a -> a -> m ()
+!= a
a = Setter' s a
l Setter' s a -> (a -> a) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%!= (a -> a -> a
forall a. Num a => a -> a -> a
+ a
a)
Setter' s a
l -!= :: Setter' s a -> a -> m ()
-!= a
a = Setter' s a
l Setter' s a -> (a -> a) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%!= a -> a -> a
forall a. Num a => a -> a -> a
subtract a
a
Setter' s a
l *!= :: Setter' s a -> a -> m ()
*!= a
a = Setter' s a
l Setter' s a -> (a -> a) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%!= (a -> a -> a
forall a. Num a => a -> a -> a
* a
a)

infixr 4 //!=

(//!=) :: (MonadState s m, Fractional a) => Setter' s a -> a -> m ()
Setter' s a
l //!= :: Setter' s a -> a -> m ()
//!= a
a = Setter' s a
l Setter' s a -> (a -> a) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%!= (a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
a)

infixr 4 &&!=, ||!=

(&&!=), (||!=) :: MonadState s m => Setter' s Bool -> Bool -> m ()
Setter' s Bool
l &&!= :: Setter' s Bool -> Bool -> m ()
&&!= Bool
a = Setter' s Bool
l Setter' s Bool -> (Bool -> Bool) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%!= (Bool -> Bool -> Bool
&& Bool
a)
Setter' s Bool
l ||!= :: Setter' s Bool -> Bool -> m ()
||!= Bool
a = Setter' s Bool
l Setter' s Bool -> (Bool -> Bool) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%!= (Bool -> Bool -> Bool
|| Bool
a)

infixr 4 <>!=

(<>!=) :: (MonadState s m, Monoid a) => Setter' s a -> a -> m ()
Setter' s a
l <>!= :: Setter' s a -> a -> m ()
<>!= a
a = Setter' s a
l Setter' s a -> (a -> a) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
Setter s s a b -> (a -> b) -> m ()
%!= (a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
a)