haskell - ReaderT静态环境

标签 haskell monad-transformers

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

向给定的 monad 添加静态环境意味着什么?

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

最佳答案

这意味着环境无法更新:您只能从中读取(因此得名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

关于haskell - ReaderT静态环境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40066909/

相关文章:

performance - Haskell 模式匹配有多快?

scala - 如何在 scalaz 7 中使用变压器在 monad 堆栈之间进行转换

scala - 为什么我们需要 Scala 中的 Monad Transformers?

haskell - monad 转换器的最佳实践 : to hide or not to hide 'liftIO'

parsing - 使普通的一元函数与等效的一元转换器一起工作

haskell - 为什么 Num 不能与 0 进行比较?

list - 是否 `(' a' :_)` represent a tuple or a list?

haskell - 插入持久化

haskell - Haskell中有任何稀疏线性代数包吗?

f# - 如何在 F# 中组合状态和延续单子(monad)