{-| State and Reader operations specialized for working with total lenses. -}

{-# LANGUAGE TypeOperators  #-}

module Data.Label.Monadic
(
-- * 'MonadState' lens operations.
  gets
, puts
, modify
, modifyAndGet
, (=:)
, (=.)

-- * 'MonadReader' lens operations.
, asks
, local
)
where

import Control.Monad
import Data.Label.Mono (Lens)

import qualified Data.Label.Total     as Total
import qualified Control.Monad.Reader as Reader
import qualified Control.Monad.State  as State

-- | Get a value out of the state, pointed to by the specified lens.

gets :: State.MonadState f m => Lens (->) f o -> m o
gets :: Lens (->) f o -> m o
gets = (f -> o) -> m o
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
State.gets ((f -> o) -> m o)
-> (Lens (->) f o -> f -> o) -> Lens (->) f o -> m o
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens (->) f o -> f -> o
forall f g o i. ((f -> g) :-> (o -> i)) -> f -> o
Total.get

-- | Set a value somewhere in the state, pointed to by the specified lens.

puts :: State.MonadState f m => Lens (->) f o -> o -> m ()
puts :: Lens (->) f o -> o -> m ()
puts Lens (->) f o
l = (f -> f) -> m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
State.modify ((f -> f) -> m ()) -> (o -> f -> f) -> o -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens (->) f o -> o -> f -> f
forall f g o i. ((f -> g) :-> (o -> i)) -> i -> f -> g
Total.set Lens (->) f o
l

-- | Modify a value with a function somewhere in the state, pointed to by the
-- specified lens.

modify :: State.MonadState f m => Lens (->) f o -> (o -> o) -> m ()
modify :: Lens (->) f o -> (o -> o) -> m ()
modify Lens (->) f o
l = (f -> f) -> m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
State.modify ((f -> f) -> m ()) -> ((o -> o) -> f -> f) -> (o -> o) -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens (->) f o -> (o -> o) -> f -> f
forall f g o i. ((f -> g) :-> (o -> i)) -> (o -> i) -> f -> g
Total.modify Lens (->) f o
l

-- | Alias for `puts' that reads like an assignment.

infixr 2 =:
(=:) :: State.MonadState f m => Lens (->) f o -> o -> m ()
=: :: Lens (->) f o -> o -> m ()
(=:) = Lens (->) f o -> o -> m ()
forall f (m :: * -> *) o.
MonadState f m =>
Lens (->) f o -> o -> m ()
puts

-- | Alias for `modify' that reads more or less like an assignment.

infixr 2 =.
(=.) :: State.MonadState f m => Lens (->) f o -> (o -> o) -> m ()
=. :: Lens (->) f o -> (o -> o) -> m ()
(=.) = Lens (->) f o -> (o -> o) -> m ()
forall f (m :: * -> *) o.
MonadState f m =>
Lens (->) f o -> (o -> o) -> m ()
modify

-- | Fetch a value pointed to by a lens out of a reader environment.

asks :: Reader.MonadReader f m => (Lens (->) f o) -> m o
asks :: Lens (->) f o -> m o
asks = (f -> o) -> m o
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
Reader.asks ((f -> o) -> m o)
-> (Lens (->) f o -> f -> o) -> Lens (->) f o -> m o
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Lens (->) f o -> f -> o
forall f g o i. ((f -> g) :-> (o -> i)) -> f -> o
Total.get

-- | Execute a computation in a modified environment. The lens is used to
-- point out the part to modify.

local :: Reader.MonadReader f m => (Lens (->) f o) -> (o -> o) -> m a -> m a
local :: Lens (->) f o -> (o -> o) -> m a -> m a
local Lens (->) f o
l o -> o
f = (f -> f) -> m a -> m a
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
Reader.local (Lens (->) f o -> (o -> o) -> f -> f
forall f g o i. ((f -> g) :-> (o -> i)) -> (o -> i) -> f -> g
Total.modify Lens (->) f o
l o -> o
f)

-- | Modify a value with a function somewhere in the state, pointed to by the
-- specified lens. Additionally return a separate value based on the
-- modification.

modifyAndGet :: State.MonadState f m => (Lens (->) f o) -> (o -> (a, o)) -> m a
modifyAndGet :: Lens (->) f o -> (o -> (a, o)) -> m a
modifyAndGet Lens (->) f o
l o -> (a, o)
f =
  do (a
b, o
a) <- o -> (a, o)
f (o -> (a, o)) -> m o -> m (a, o)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
`liftM` Lens (->) f o -> m o
forall f (m :: * -> *) o. MonadState f m => Lens (->) f o -> m o
gets Lens (->) f o
l
     Lens (->) f o -> o -> m ()
forall f (m :: * -> *) o.
MonadState f m =>
Lens (->) f o -> o -> m ()
puts Lens (->) f o
l o
a
     a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
b