haskell - 如何让 Reader 和 ReaderT 协同工作

标签 haskell monads

我正在使用 ReaderT Monad 转换器通过多个执行 IO 的函数从主函数传播配置数据。需要数据的最终函数不执行任何 IO。我有这个工作解决方案:

import Control.Monad.Reader

type Configuration = String

funNoIO :: Reader Configuration String
funNoIO = do
    config <- ask
    return $ config ++ "!"

funIO :: ReaderT Configuration IO String
funIO = do
    config <- ask
    return $ runReader funNoIO config

main :: IO ()
main = do
    c <- runReaderT funIO "configuration"
    print c

但它迫使我检索 funIO 函数中我不需要的配置。

我是这样修改的:

funIO' :: ReaderT Configuration IO String
funIO' = do
    v <- funNoIO
    return v

但它无法编译,我收到此错误:

Couldn't match type ‘ReaderT Configuration Identity String’
              with ‘Identity (ReaderT Configuration IO String)’
Expected type: Identity (ReaderT Configuration IO String)
  Actual type: Reader Configuration String
In the first argument of ‘runIdentity’, namely ‘funNoIO’
In a stmt of a 'do' block: v <- runIdentity funNoIO

是否可以将我的配置数据传播到纯函数,而不在中间 IO 函数中检索它?

编辑

我参数化了函数,但仍然无法在 funIO' 函数中执行 IO 操作。例如:

getMessage :: IO String
getMessage = do
    return "message"

funIO' :: MonadIO m => ReaderT Configuration m String
funIO' = do
    m <- getMessage
    v <- funNoIO
    return $ v ++ m

给我以下错误:

Couldn't match type ‘IO’ with ‘ReaderT Configuration m’
Expected type: ReaderT Configuration m String
Actual type: IO String

编辑2

我明白了,我只需要使用liftIO:

getMessage :: IO String
getMessage = do
    return "message"

funIO' :: MonadIO m => ReaderT Configuration m String
funIO' = do
    m <- liftIO getMessage
    v <- funNoIO
    return $ v ++ m

最佳答案

另一种方法是将 MonadReaderreader 方法与 runReader 一起使用:

funIO = reader $ runReader funNoIO

读者。 runReader 从纯 Reader monad 转换为更通用的 MonadReader 实例。

关于haskell - 如何让 Reader 和 ReaderT 协同工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28400197/

相关文章:

parsing - 在解析器组合器中组合词法分析器和解析器

haskell - Jupyter 和 Haskell - 包

performance - 从 Haskell 中的 monadic 流中榨取更多性能

scala - Monad for-comprehensions with implicit Monad 失败,使用继承?

java - 使用 Java 8 的 Monad

scala - 到底是什么让 Option 成为 Scala 中的 monad?

Haskell hGetLine 和空字符

Haskell 错误不在范围内 : data constructor

Haskell:理解 do 符号与 if-else 语句

multithreading - Haskell 中的 "spark"是什么