【问题标题】:ReaderT static environmentReaderT 静态环境
【发布时间】:2017-02-25 06:54:04
【问题描述】:

ReaderT monad 转换器的声明,它将静态环境添加到给定的 monad。

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

有人建议这与另一个问题重复。我相信这个问题是独一无二的,因为我在问拥有静态环境意味着什么,而且我的问题与 ReaderT 有关。即便和Reader类似,但还是有区别的。

【问题讨论】:

标签: haskell monad-transformers


【解决方案1】:

这意味着环境不能被更新:你只能读取它(因此得名ReaderT)。这与 StateT 这样的 monad 转换器形成鲜明对比,后者为您提供了一个可以读写的环境。


在 reader 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

【讨论】:

  • 我能达到这个环境吗?
  • 如果我想要我需要的环境是不是
  • 应该给出一个使用例子,让OP更好地理解你在说什么。类型不会自己与初学者交谈,记住这一点很重要......
  • @Alec 感谢您抽出宝贵的时间来写这篇文章!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
相关资源
最近更新 更多