如何嵌套monad

 网络小爬虫 发布于 2023-02-13 11:17

我在Haskell中有这个代码:

import Control.Monad.Trans.State

simpleState = state (\x -> (x, x + 1))

runUntil :: (s -> Bool) -> State s a -> State s a
runUntil f s = do
    s' <- get
    -- Here I want to print value of s' to console
    if f s'
        then s >> runUntil f s
        else s

main :: IO ()
main = do
    let (x,s) = runState (runUntil (< 10) simpleState) 0
    putStrLn $ "State = " ++ (show s) ++ " Result = " ++ (show x)

我想在runUntil的每次迭代中打印状态的值.
如果我不能在runUntil功能上打印它我可以做到这一点?

1 个回答
  • 欢迎来到Monad变形金刚的精彩世界.有一个很好的库叫MTL,提供大多数monad的"monad transformer"等价物.按照惯例,这些以大写字母T结束,StateT我们想要的也是如此.Monad的变压器具有其通常的操作和多一个,lift为一个StateT看起来像这样,

    lift :: Monad m => m a -> StateT s m a
    

    现在有一个特殊的变压器类在IO被调用之上MonadIO.要使用它,我们会做类似的事情.它类似于一个普通的旧monad变换器,但具有类型签名

    liftIO :: (MonadIO m, Monad m) => IO a -> m a
    
     import Control.Monad.State
     import Control.Monad.Trans
    
     simpleState :: StateT Integer IO ()
     simpleState = modify (+1)
    
     runUntil :: Show s => (s -> Bool) -> StateT s IO a -> StateT s IO s
     runUntil pred newState = do
        curr <- get
        if pred curr
        then liftIO (print curr) >> newState >> runUntil pred newState
        else return curr
    

    然后运行它,有一套方便的函数可以转换StateT s m as -> (s, a).

    main :: IO ()
    main = do
      (x,s) <- runStateT (runUntil (< 10) simpleState) 0
      putStrLn $ "State = " ++ (show s) ++ " Result = " ++ (show x)
    

    请注意,现在我们使用bind(the <-)因为结果是IO,它不再是纯粹的.Monad变形金刚可能会让人感到困惑,幸运的是,Real World Haskell有一章介绍它们.如果你感到困惑,那值得一看.

    2023-02-13 11:19 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有