{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module Snap.Snaplet.Internal.LensT where
import Control.Applicative (Alternative (..),
Applicative (..))
import Control.Category ((.))
import Control.Lens (ALens', cloneLens, storing, (^#))
import Control.Monad (MonadPlus (..))
import Control.Monad.Base (MonadBase (..))
import Control.Monad.Reader (MonadReader (..))
import Control.Monad.State.Class (MonadState (..))
import Control.Monad.Trans (MonadIO (..), MonadTrans (..))
import Control.Monad.Trans.Control (ComposeSt, MonadBaseControl (..),
MonadTransControl (..),
defaultLiftBaseWith,
defaultLiftWith, defaultRestoreM,
defaultRestoreT)
import Prelude (Functor (..), Monad (..), const,
($), ($!))
import Snap.Core (MonadSnap (..))
import Snap.Snaplet.Internal.RST (RST (..), runRST, withRST)
newtype LensT b v s m a = LensT (RST (ALens' b v) s m a)
deriving ( Monad
, MonadTrans
, Functor
, Applicative
, MonadIO
, MonadPlus
, Alternative
, MonadReader (ALens' b v))
instance Monad m => MonadState v (LensT b v b m) where
get = lGet
put = lPut
instance MonadBase bs m => MonadBase bs (LensT b v s m) where
liftBase = lift . liftBase
instance MonadBaseControl bs m => MonadBaseControl bs (LensT b v s m) where
type StM (LensT b v s m) a = ComposeSt (LensT b v s) m a
liftBaseWith = defaultLiftBaseWith
restoreM = defaultRestoreM
{-# INLINE liftBaseWith #-}
{-# INLINE restoreM #-}
instance MonadTransControl (LensT b v s) where
type StT (LensT b v s) a = StT (RST (ALens' b v) s) a
liftWith = defaultLiftWith LensT (\(LensT rst) -> rst)
restoreT = defaultRestoreT LensT
{-# INLINE liftWith #-}
{-# INLINE restoreT #-}
instance MonadSnap m => MonadSnap (LensT b v s m) where
liftSnap m = LensT $ liftSnap m
getBase :: Monad m => LensT b v s m s
getBase = LensT get
{-# INLINE getBase #-}
putBase :: Monad m => s -> LensT b v s m ()
putBase = LensT . put
{-# INLINE putBase #-}
lGet :: Monad m => LensT b v b m v
lGet = LensT $ do
!l <- ask
!b <- get
return $! b ^# l
{-# INLINE lGet #-}
lPut :: Monad m => v -> LensT b v b m ()
lPut v = LensT $ do
!l <- ask
!b <- get
put $! storing l v b
{-# INLINE lPut #-}
runLensT :: Monad m => LensT b v s m a -> ALens' b v -> s -> m (a, s)
runLensT (LensT m) l = runRST m l
{-# INLINE runLensT #-}
withLensT :: Monad m
=> (ALens' b' v' -> ALens' b v)
-> LensT b v s m a
-> LensT b' v' s m a
withLensT f (LensT m) = LensT $ withRST f m
{-# INLINE withLensT #-}
withTop :: Monad m
=> ALens' b v'
-> LensT b v' s m a
-> LensT b v s m a
withTop subLens = withLensT (const subLens)
{-# INLINE withTop #-}
with :: Monad m => ALens' v v' -> LensT b v' s m a -> LensT b v s m a
with subLens = withLensT (\l -> cloneLens l . subLens)