ReaderT静态环境

时间:2016-10-16 04:42:07

标签: haskell monad-transformers

  

声明ReaderT monad变换器,它为给定的monad添加静态环境。

将静态环境添加到给定的monad是什么意思?

有人建议这与另一个问题重复。我相信这个问题是独一无二的,因为我问的是有一个静态环境意味着什么,我的问题也与ReaderT有关。即使它与Reader类似,它们仍然是不同的。

1 个答案:

答案 0 :(得分:2)

这意味着无法更新环境:您只能从中读取(因此名称为ReaderT)。这与像StateT这样的monad变换器形成对比,后者为您提供了一个可以读写的环境。

在读者monad中,您可以使用ask函数访问环境:

ask :: Monad m => ReaderT r m r 

在状态monad中,你有一个类似的函数用于读取名为get的函数以及另一个写入put状态的函数:

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

实施例

以下是ReaderTStateT的示例用法。让我们假设我的基础monad将是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

然后,如果您多次运行阅读器版本,请注意您尝试猜测的值永远不会改变。状态版本不是这种情况,每次做出错误猜测时都会重置为新数字:

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