【问题标题】:Composing IO Monads using do使用 do 组合 IO Monad
【发布时间】:2013-11-15 12:45:50
【问题描述】:

我在 Reader Monad 中有代码,以便将文件句柄作为不可见参数传递到 Reader 链中。

在 writeMail 中,我正在尝试创建一个 Reader,它在使用 runReader 运行时会产生一个 IO () 输出,该输出本身就是一系列 IO monads 的结果

writeMail :: Reader Handle (IO ())
writeMail mail = do
 wmh <- writeMailHeaders mail
 wmb <- writeMailBody mail
return $ wmh >>= \_ -> wmb

但是我发现只有 IO 链中的最后一个,即 wmb,在控制台上打印。

谁能看到我应该怎么做才能得到 wmh,然后再打印 wmb?

【问题讨论】:

    标签: haskell io monads


    【解决方案1】:

    用更简单的例子:

    module Read where
    
    import Data.Functor.Identity
    
    write :: Monad m => m (IO ())
    write = do
      a <- return $ putStrLn "foo"
      b <- return $ putStrLn "bar"
      return $ a >> b
    
    main :: IO ()
    main = runIdentity write
    

    main 打印“foo”和“bar”。所以我怀疑错误在writeMailHeaders。

    【讨论】:

      【解决方案2】:

      您需要的不仅仅是一个阅读器,而是一个以IO 为基本 monad 的 ReaderT monad 转换器。

      由于您的示例不完整,因此我进行了一些更改以显示您的选项:

      import Control.Monad.Reader
      
      writeMail :: ReaderT Handle IO ()
      writeMail = do
      
        -- Here's how you get your handle to further do something to it:
        handle <- ask
      
        -- Here's how you do the IO actions.
        -- Notice the `lift` function, 
        -- which allows us to run actions of the base monad,
        -- which in that case is `IO`.
        lift $ do
          print "bla bla"
          print "bla"
      

      【讨论】:

      • 我不是 OP,但我认为 monad 转换器的基本使用对我来说刚刚好。非常感谢。
      • 是的。我记得同样的感觉。直到某个时刻,这对我来说都是巫术,当“点击”时意识到它的简单性。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-08
      • 1970-01-01
      • 2022-01-22
      相关资源
      最近更新 更多