content: {-| 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 = State.gets . 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 l = State.modify . Total.set 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 l = State.modify . Total.modify l
  
  -- | Alias for `puts' that reads like an assignment.
  
  infixr 2 =:
  (=:) :: State.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 ()
  (=.) = 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 = Reader.asks . 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 l f = Reader.local (Total.modify l 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 l f =
    do (b, a) <- f `liftM` gets l
       puts l a
       return b
  
  