ReaderT статическая среда

Декларация ReaderT преобразователь монад, который добавляет статическую среду к данной монаде.

Что значит добавить статическую среду к данной монаде?

Кто-то предположил, что это дубликат другого вопроса. Я считаю, что этот вопрос уникален, потому что я спрашиваю, что значит иметь статическую среду, а также мой вопрос относится к ReaderT. Даже если это похоже на Reader, они все равно разные.

1 ответ

Решение

Это означает, что среда не может быть обновлена: вы можете только читать из нее (отсюда и название ReaderT). Это в отличие от монадных трансформаторов, таких как StateT которые предоставляют вам среду, в которую вы можете читать и писать.


Внутри читательской монады вы можете достичь окружения, используя ask функция:

ask :: Monad m => ReaderT r m r 

Внутри государственной монады у вас есть похожая функция для чтения, которая называется get а также другая функция, которая пишет в состояние под названием put:

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

Примеры

Вот пример использования обоих ReaderT а также StateT, Давайте предположим, что моя основная монада будет IO так что я смогу напечатать вещи по пути.

Придуманный пример - это программа угадывания чисел - среда - это просто число, которое вы пытаетесь угадать (так Int). guess берет номер и проверяет, совпадает ли номер с номером в среде. Если нет, то выводит сообщение на экран. В любом случае возвращается, было ли ваше предположение успешным.

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

Однако предположим, что теперь вам нужен способ изменения числа, которое вы пытаетесь угадать случайным образом после предположения. Тогда, так как вам нужно изменить среду, вам нужно будет использовать 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

Затем, если вы запустите версию Reader несколько раз, обратите внимание, что значение, которое вы пытаетесь угадать, никогда не изменится. Это не относится к версии состояния, которая сбрасывается на новый номер каждый раз, когда вы делаете неправильное предположение:

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
Другие вопросы по тегам