1{-# LANGUAGE ExistentialQuantification #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE InstanceSigs #-}
5{-# LANGUAGE MultiParamTypeClasses #-}
6{-# LANGUAGE Rank2Types #-}
7{-# LANGUAGE RecordWildCards #-}
8{-# LANGUAGE ScopedTypeVariables #-}
9{-# LANGUAGE TypeFamilies #-}
10{-# LANGUAGE UndecidableInstances #-}
21import Control.Applicative (Alternative (..))
22import Control.Monad.Base (MonadBase (..), liftBaseDefault)
23import Control.Monad.Catch (MonadThrow, throwM)
24import Control.Monad.State (MonadIO (..), MonadPlus (..),
25 MonadState (..), StateT (..),
26 liftM, gets, modify, runStateT, when)
27import Control.Monad.Trans.Class (MonadTrans (lift))
28import Control.Monad.Trans.Control (ComposeSt, MonadBaseControl (..),
29 MonadTransControl (..),
32import Data.Dynamic (TypeRep, Typeable, typeOf)
33import qualified Data.Map as M
37------------------------------------------------------------------------------
38-- * Extensible State: Session Data Management
39------------------------------------------------------------------------------
41-- | Same as 'getSData' but with a more general type. If the data is found, a
42-- 'Just' value is returned. Otherwise, a 'Nothing' value is returned.
43getData :: (MonadState Context m, Typeable a) => m (Maybe a)
47 case M.lookup (typeOf $ typeResp resp) list of
48 Just x -> return . Just $ unsafeCoerce x
49 Nothing -> return Nothing
50 typeResp :: m (Maybe x) -> x
53-- | Same as 'setSData' but with a more general type.
54setData :: (MonadState Context m, Typeable a) => a -> m ()
55setData x = modify $ \st -> st { mfData = M.insert t (unsafeCoerce x) (mfData st) }
58modifyData :: (MonadState Context m, Typeable a) => (Maybe a -> Maybe a) -> m ()
59modifyData f = modify $ \st -> st { mfData = M.alter alterf t (mfData st) }
60 where typeResp :: (Maybe a -> b) -> a
62 t = typeOf (typeResp f)
63 alterf mx = unsafeCoerce $ f x'
65 Just x -> Just $ unsafeCoerce x
68delData :: (MonadState Context m, Typeable a) => a -> m ()
69delData x = modify $ \st -> st { mfData = M.delete (typeOf x) (mfData st) }
71------------------------------------------------------------------------------
72-- * Extensible State: Session Data Management
73------------------------------------------------------------------------------
75-- | Retrieve a previously stored data item of the given data type from the
76-- monad state. The data type to retrieve is implicitly determined from the
77-- requested type context.
78-- If the data item is not found, an 'empty' value (a void event) is returned.
79-- Remember that an empty value stops the monad computation. If you want to
80-- print an error message or a default value in that case, you can use an
81-- 'Alternative' composition. For example:
83-- > getSData <|> error "no data"
84-- > getInt = getSData <|> return (0 :: Int)
85getSData :: (Monad m, Typeable a) => AsyncT m a
86getSData = AsyncT getData
88-- | 'setSData' stores a data item in the monad state which can be retrieved
89-- later using 'getData' or 'getSData'. Stored data items are keyed by their
90-- data type, and therefore the data type must be 'Typeable' and only one item
91-- of a given type can be stored. A newtype wrapper can be used to distinguish
92-- two data items of the same type when required.
95-- import Control.Monad.IO.Class (liftIO)
96-- import Transient.Base
97-- import Data.Typeable
99-- data Person = Person
102-- } deriving Typeable
105-- setSData $ Person "Alberto" 55
106-- Person name age <- getSData
107-- liftIO $ print (name, age)
109setSData :: (Monad m, Typeable a) => a -> AsyncT m ()
110setSData x = AsyncT $ setData x >> return (Just ())
112-- | Accepts a function that takes the current value of the stored data type
113-- and returns the modified value. If the function returns 'Nothing' the value
114-- is deleted otherwise updated.
115modifySData :: (Monad m, Typeable a) => (Maybe a -> Maybe a) -> AsyncT m ()
116modifySData x = AsyncT $ modifyData x >> return (Just ())
118-- | Delete the data item of the given type from the monad state.
119delSData :: (Monad m, Typeable a) => a -> AsyncT m ()
120delSData x = AsyncT $ delData x >> return (Just ())
122------------------------------------------------------------------------------
123-- MonadState for AsyncT m
124------------------------------------------------------------------------------
126instance (Monad m, Monad (AsyncT m)) => MonadState Context (AsyncT m) where
127 get = AsyncT $ get >>= return . Just
128 put x = AsyncT $ put x >> return (Just ())
129 state f = AsyncT $ do
136-- | Run an action, if the result is a void action undo any state changes
137-- that it might have caused.
138try :: MonadIO m => AsyncT m a -> AsyncT m a
141 mx <|> (modify (\s -> s { mfData = sd }) >> empty)
143-- | Executes the computation and reset the state either if it fails or not
144sandbox :: MonadIO m => AsyncT m a -> AsyncT m a
147 mx <*** modify (\s ->s { mfData = sd})
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list