{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Lib where import Control.Lens (makeLenses) import Control.Monad.Identity (Identity(..)) import Control.Monad.Reader (ReaderT(..), runReaderT) import Control.Monad.Reader.Class (MonadReader(..)) import Control.Monad.State.Class (MonadState(..)) import Control.Monad.State.Strict (StateT(..), evalStateT) import Data.Default (Default(..)) data Position = Position { _x :: Int, _y :: Int } deriving (Show, Read) instance Default Position where def = Position 0 0 makeLenses ''Position data Player = Player { position :: Position} deriving (Show, Read) instance Default Player where def = Player { position = def } makeLenses ''Player newtype Config = Config String deriving (Show) data World = World { player :: Player} deriving (Show, Read) instance Default World where def = World { player = def } makeLenses ''World newtype App a = App { runApp :: StateT World (ReaderT Config Identity) a} deriving ( Applicative , Functor , Monad , MonadState World , MonadReader Config ) evalApp :: App a -> World -> Config -> a evalApp f world config = runIdentity (runReaderT (evalStateT (runApp f) world) config)