{-# LANGUAGE TypeOperators  #-}
module Data.Label.PureM
(
-- * 'MonadState' lens operations.
  gets
, puts
, modify
, (=:)
, (=.)

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

import Data.Label.Pure ((:->))
import qualified Control.Monad.Reader as M
import qualified Control.Monad.State  as M
import qualified Data.Label.Pure      as L

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

gets :: M.MonadState s m => s :-> a -> m a
gets = M.gets . L.get

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

puts :: M.MonadState s m => s :-> a -> a -> m ()
puts l = M.modify . L.set l

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

modify :: M.MonadState s m => s :-> a -> (a -> a) -> m ()
modify l = M.modify . L.modify l

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

infixr 2 =:
(=:) :: M.MonadState s m => s :-> a -> a -> m ()
(=:) = puts

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

infixr 2 =.
(=.) :: M.MonadState s m => s :-> a -> (a -> a) -> m ()
(=.) = modify

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

asks :: M.MonadReader r m => (r :-> a) -> m a
asks = M.asks . L.get

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

local :: M.MonadReader r m => (r :-> b) -> (b -> b) -> m a -> m a
local l f = M.local (L.modify l f)