ReaderT static environment

纵然是瞬间 提交于 2019-12-12 21:24:07

问题


Declaration of the ReaderT monad transformer, which adds a static environment to a given monad.

What does it mean to add a static environment to a given monad?

Someone suggested that this is a duplicate to another question. I believe that this question is unique because I'm asking what it means to have a static environment and also my question pertains to ReaderT. Even if it is similar to Reader, they are still different.


回答1:


It means that the environment cannot be updated: you can only read from it (hence the name of ReaderT). This is in contrast to monad transformers like StateT which provide you an environment you can both read and write to.


Inside a reader monad, you can reach the envionment using the ask function:

ask :: Monad m => ReaderT r m r 

Inside a state monad, you have a similar function for reading called get as well as another function which writes to the state called put:

get :: Monad m => StateT s m s 
put :: Monad m => s -> StateT s m ()

Examples

Here is a sample usage of both ReaderT and StateT. Let's suppose my underlying monad will be IO so that I will be able to print things along the way.

The contrived example here is a number guessing program - the environment is just a number that you are trying to guess (so Int). guess takes a number and checks whether the number is the same one as the one in the environment. If not, it prints a message to the screen. In either case, it returns whether your guess was successful.

guessReader :: Int -> ReaderT Int IO Bool
guessReader guess = do
  actual <- ask
  if guess == actual
    then return True
    else do
      lift $ putStrLn ("The number was " ++ show actual)
      return False

However, suppose now you want a way of changing the number you are trying to guess randomly after a guess. Then, since you need to change the environment, you will need to use StateT.

import System.Random (randomRIO)

guessState :: Int -> StateT Int IO Bool
guessState guess = do
   actual <- get
   if guess == actual
     then return True
     else do
       lift $ putStrLn ("The number was " ++ show actual)
       newActual <- lift $ randomRIO (0,10)
       put newActual
       return False

Then, if you run the reader version several times, note that the value you are trying to guess never changes. That is not the case with the state version, which resets to a new number every time you make a wrong guess:

ghci> runReaderT (guessReader 3 >> guessReader 4 >> guessReader 5) 5
The number was 5
The number was 5
True
ghci> evalStateT (guessState 3 >> guessState 4 >> guessState 5) 5
The number was 5
The number was 6
The number was 2
False


来源:https://stackoverflow.com/questions/40066909/readert-static-environment

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!