monad-state-0.2.0.1: src/Control/Monad/Record.hs
{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, TypeOperators, PostfixOperators, FlexibleInstances #-}
-- TODO: support fclabels-1.0 with CPP; c.f. documentation for one of the
-- instance declaration of 'MLens'
module Control.Monad.Record
( maybeAbort
, maybeAbortM
, lensGS
, MLens(..)
, (:-->)(..)
, getM
, setM
, modM
, getMAbort
, setMAbort
, modMAbort
, askM
, liftState
, liftSubState
, liftSubMaybeState
, (<:)
, (=:)
, ($:)
, (<::)
, (=::)
, ($::)
, (<<:)
, (<=:)
, (<$:)
, (<<::)
, (<->)
, (<:<)
, (>$<)
, (>$>)
, (>$$>)
, module Data.Label
--, module Data.Label.Abstract
, module Data.Label.Poly
, module Data.Label.Point
) where
import Prelude hiding ((.), id)
import Control.Category
import Control.Monad.Abort
import Control.Monad.Reader
import Control.Monad.State.Strict hiding (get, modify)
import qualified Control.Monad.State.Strict as S (modify)
import Control.Monad.Trans.Maybe
import Data.Label
--import Data.Label.Abstract (Lens)
import Data.Label.Poly (Lens)
import Data.Label.Point (Total)
maybeAbort :: (Monad m) => r -> Maybe a -> AbortT r m a
maybeAbort _ (Just x) = return x
maybeAbort r (Nothing) = abort r
maybeAbortM :: (MonadTrans t, Monad m, MonadAbort (t m)) => AbortResultType (t m) -> MaybeT m a -> t m a
maybeAbortM r m = do
x <- lift . runMaybeT $ m
case x of
(Just a) -> return a
(Nothing) -> abort r
-- | Create a lens out of a getter and setter.
lensGS :: (f -> a) -> (a -> f -> f) -> f :-> a
-- This function definition can be made to work with the following versions of
-- fc-labels; all ranges are inclusive:
-- * 1.0 - 1.1.7.1:
--lensGS = lens
-- * 2.0 - onward:
lensGS getter setter = lens getter (\modifier f -> setter (modifier (getter f)) f)
class MLens l a f where
type MLensA l a f
type MLensF l a f
toLens :: l f a -> (MLensF l a f) :-> Maybe (MLensA l a f)
--toLens :: l f a -> f :-> Maybe (MLensA l a f)
--instance MLens (:->) (Maybe a) (Maybe o) where
-- fc-labels versions as old as 1.0 will work with this package so long as
-- @Total@ is replaced with @(->)@, and in the import and export of
-- Data.Label.Poly, @Mono@ is replaced with @Abstract@, and finally in this
-- instance declaration, @Maybe i -> Maybe i@ is replaced with @Maybe i@ and
-- @Maybe o -> Maybe o@ is replaced with @Maybe o@; and the instructions in the
-- documentation for lensGS are applied.
--instance MLens (Lens (->)) (Maybe i) (Maybe o) where
instance MLens (Lens Total) (Maybe i -> Maybe i) (Maybe o -> Maybe o) where
--type MLensA (Lens (->)) (Maybe i) (Maybe o) = i
type MLensA (Lens Total) (Maybe i -> Maybe i) (Maybe o -> Maybe o) = i
--type MLensF (Lens (->)) (Maybe i) (Maybe o) = Maybe o
type MLensF (Lens Total) (Maybe i -> Maybe i) (Maybe o -> Maybe o) = Maybe o
toLens = id
instance MLens (:-->) a f where
type MLensA (:-->) a f = a
type MLensF (:-->) a f = f
toLens = unMaybeLens
newtype f :--> a = MaybeLens {unMaybeLens :: f :-> Maybe a}
instance Category (:-->) where
id = MaybeLens $ lensGS Just (\a f -> maybe f id a)
MaybeLens a . MaybeLens b = MaybeLens $ lensGS getter setter
where getter f = get a =<< get b f
setter = modify b . fmap . set a
getM :: (MonadState m) => (StateType m :-> a) -> m a
getM = gets . get
setM :: (MonadState m) => (StateType m :-> a) -> a -> m ()
setM l = S.modify . set l
modM :: (MonadState m) => (StateType m :-> a) -> (a -> a) -> m ()
modM l = S.modify . modify l
getMAbort :: (MonadState m, MLens l b f, MLensF l b f ~ StateType m) => r -> l f b -> (MLensA l b f :-> a) -> AbortT r m a
getMAbort r b l = liftM (get l) $ maybeAbort r =<< gets (get $ toLens b)
setMAbort :: (MonadState m, MLens l b f, MLensF l b f ~ StateType m) => l f b -> (MLensA l b f :-> a) -> a -> m ()
setMAbort b l x = S.modify . modify (toLens b) . fmap $ set l x
modMAbort :: (MonadState m, MLens l b f, MLensF l b f ~ StateType m) => l f b -> (MLensA l b f :-> a) -> (a -> a) -> m ()
modMAbort b l f = S.modify . modify (toLens b) . fmap $ modify l f
askM :: (MonadReader m) => (EnvType m :-> a) -> m a
askM = asks . get
liftState :: (MonadState m) => (StateType m :-> s) -> StateT s m a -> m a
liftState l n = do
(a, s) <- runStateT n =<< (l <::)
l =:: s
return a
liftSubState :: (Monad m, MonadTrans t, MonadState (t m)) => (StateType (t m) :-> s) -> StateT s m a -> t m a
liftSubState l m = do
s <- getM l
(a, s') <- lift . runStateT m $ s
setM l s'
return a
liftSubMaybeState :: (Monad m, MonadTrans t, MonadState (t m), MLens l b f, MLensF l b f ~ StateType (t m)) => l f b -> StateT (MLensA l b f) m a -> MaybeT (t m) a
liftSubMaybeState l m = MaybeT $ do
sw <- getM l'
case sw of
(Just s) -> do
(a, s') <- lift . runStateT m $ s
setM l' $ Just s'
return $ Just a
(Nothing) -> do
return Nothing
where l' = toLens l
-- | 'get'
infixr 8 <::
(<:) :: (f :-> a) -> f -> a
(<:) = get
-- | 'set'
infixr 5 =::
(=:) :: (f :-> a) -> a -> f -> f
(=:) = set
-- | 'modify'
infixr 8 $::
($:) :: (f :-> a) -> (a -> a) -> f -> f
($:) = modify
-- | 'getM'
infixr 8 <:
(<::) :: (MonadState m) => (StateType m :-> a) -> m a
(<::) = getM
-- | 'setM'
infixr 5 =:
(=::) :: (MonadState m) => (StateType m :-> a) -> a -> m ()
(=::) = setM
-- | 'modM'
infixr 8 $:
($::) :: (MonadState m) => (StateType m :-> a) -> (a -> a) -> m ()
($::) = modM
-- | 'getMAbort'
infixr 8 <<:
(<<:) :: (MonadState m, MLens l b f, MLensF l b f ~ StateType m) => r -> l f b -> (MLensA l b f :-> a) -> AbortT r m a
(<<:) = getMAbort
-- | 'setMAbort'
infixr 5 <=:
(<=:) :: (MonadState m, MLens l b f, MLensF l b f ~ StateType m) => l f b -> (MLensA l b f :-> a) -> a -> m ()
(<=:) = setMAbort
-- | 'modMAbort'
infixr 8 <$:
(<$:) :: (MonadState m, MLens l b f, MLensF l b f ~ StateType m) => l f b -> (MLensA l b f :-> a) -> (a -> a) -> m ()
(<$:) = modMAbort
-- | 'getMAbort' ()
infixr 8 <<::
(<<::) :: (MonadState m, MLens l b f, MLensF l b f ~ StateType m) => l f b -> (MLensA l b f :-> a) -> AbortT () m a
(<<::) = getMAbort ()
infixr 5 <->
(<->) :: (MLens l a f, MLens l' a' f', MLensA l a f ~ MLensF l' a' f') => l' f' a' -> l f a -> MLensF l a f :--> MLensA l' a' f'
a <-> b = (MaybeLens . toLens $ a) . (MaybeLens . toLens $ b)
-- | 'askM'
infixr 5 <:<
(<:<) :: (MonadReader m) => (EnvType m :-> a) -> m a
(<:<) = askM
-- | 'liftState'
infixr 4 >$<
(>$<) :: (MonadState m) => (StateType m :-> s) -> StateT s m a -> m a
(>$<) = liftState
-- These functions have more restrictive types than the functions to which their functionality is equivalent, to resolve some errors caused by too general types
-- | 'liftSubState'
infixr 5 >$>
(>$>) :: (Monad m) => (s :-> s') -> StateT s' m a -> StateT s m a
(>$>) = liftSubState
-- | 'liftSubMaybeState'
infixr 4 >$$>
(>$$>) :: (Monad m, MonadTrans t, MonadState (t m), MLens l b f, MLensF l b f ~ StateType (t m)) => l f b -> StateT (MLensA l b f) m a -> MaybeT (t m) a
(>$$>) = liftSubMaybeState