{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Monad.Trans
import Control.Monad.Trans.State
import Control.Monad.Trans.Reader
import Control.Monad.Identity
import qualified Control.Monad.State as S
import qualified Control.Monad.Reader as R
data AppState = AppState Int deriving Show
data AppConfig = AppConfig String deriving Show
type App = ReaderT AppConfig (StateT AppState Identity)
app :: App String
app = do
(AppConfig config) <- ask
(AppState st) <- lift S.get
S.put (AppState $ st + 1)
return $ config ++ " " ++ show st
runApp :: App a -> String -> Identity (a, AppState)
runApp app conf =
let config = AppConfig conf
state = AppState 0
in runStateT (runReaderT app config) state
-- runIdentity $ runApp app "a"
---
newtype MyApp a = MyA {
runA :: ReaderT AppConfig (StateT AppState Identity) a
} deriving (Functor, Applicative, Monad, R.MonadReader AppConfig, S.MonadState AppState)
myApp :: MyApp String
myApp = do
(AppConfig config) <- R.ask
(AppState st) <- S.get
S.put (AppState $ st + 1)
return $ config ++ " " ++ show st
runMyApp :: MyApp a -> String -> Identity (a, AppState)
runMyApp k maxDepth =
let config = AppConfig maxDepth
state = AppState 0
in runStateT (runReaderT (runA k) config) state
-- runIdentity $ runMyApp myApp "hello"
---
main = do
print $ runIdentity $ runApp app "hello"
print $ runIdentity $ runMyApp myApp "hello"