I need to learn to use the Reader monad. (And also the Writer and State).
The game-contests I do always consists in global parameters that are valid throughout the Game. And a bunch of parameters that are valid only during one Turn.
I ended all the latest contests with lots and lots of functions that almost all had Game and Turn as input parameters.
After having read about the reader monad, I am thinking about having:
data Game = Game AllNeeded StrategicPositions AndGameRelatedStuffs
data Turn = Turn PlayersPositions AndTurnDependentStuffs
and for each loop when I receive turn dependent data, I plan to have a variable Reader Game Turn
:
turnReader = Reader currentGame currentTurn
let actionToPerform = play turnReader
Do you think it's the good example of application for the Reader monad ? Do you think I can/should go blindfold and learn to use the Reader monad in this context ? Or is there a more appropriate monad for this, like State ?
The Reader monad (also called the Environment monad). Represents a computation, which can read values from a shared environment, pass values from function to function, and execute sub-computations in a modified environment. Using Reader monad for such computations is often clearer and easier than using the State monad.
The function monad allows you to sequence or compose functions together. The first function in the chain can only take one parameter and the rest have to take two parameters. After you're done composing functions together using join , apply , and pure , the returned function will only take one input.
The state monad is a built in monad in Haskell that allows for chaining of a state variable (which may be arbitrarily complex) through a series of function calls, to simulate stateful code.
A monad is an algebraic structure in category theory, and in Haskell it is used to describe computations as sequences of steps, and to handle side effects such as state and IO. Monads are abstract, and they have many useful concrete instances. Monads provide a way to structure a program.
The Reader
monad is used when you have an immutable state that you want to read in your computation. Is basically like having an extra argument implicitly passed to all the monadic actions.
It seems like in your game you actually want to change something (i.e. turn, or state of the game). In this case a State
monad may be easier to work with.
In order to use Reader
you have to group all actions that depend on the state, execute them in the monad then outside the monad change the state and run a new monadic computation with the modified state etc. This sounds cumbersome.
Note that using Reader
is actually similar to using State
. Simply: the put
operation (and derivatives) are disallowed. So you could start writing using Reader
and if you encounter a place were you'd like to modify the state you know that it would probably be better to use State
.
Or viceversa: start by using State
and if you end up never modifying the state replace it with Reader
.
It seems reasonable to have something like StateT Turn (ReaderT Game IO)
, assuming Turn
value changes every turn and Game
doesn't. You'll need to read up on monad transformers for this (I personally like "Monad Transformers Step by Step" (PDF)).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With