{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} module Lib where import Control.Lens (makeLenses) import Control.Monad.Identity (Identity(..)) import Control.Monad.IO.Class (MonadIO(..)) 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 IO) a} deriving ( Applicative , Functor , Monad , MonadState World , MonadReader Config , MonadIO ) evalApp :: App a -> World -> Config -> IO a evalApp f world config = runReaderT (evalStateT (runApp f) world) config