    {-| 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 l :: 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 l :: 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 l :: Lens (->) f o
    l f :: 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 l :: Lens (->) f o
    l f :: o -> (a, o)
    f =
      do (b :: a
    b, a :: 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