【问题标题】:iterate + forever = iterateM? Repeating an action with feedback迭代 + 永远 = iterateM?使用反馈重复操作
【发布时间】:2012-05-29 14:19:53
【问题描述】:

我试图永远重复一个 IO 操作,但是将一次执行的结果输入到下一次执行中。像这样的:

-- poorly named
iterateM :: Monad m => (a -> m a) -> a -> m b
iterateM f a = f a >>= iterateM f

Hoogle 似乎没有帮助我,但我看到很多功能看起来非常接近我想要的,但似乎没有一个功能完全符合。

【问题讨论】:

  • 我创建了一个iterateM_ 函数作为this question 的答案。
  • @pat:很高兴看到我不是唯一一个!

标签: haskell monads


【解决方案1】:

你说得对,我不知道这种特殊循环在哪里实现。你的实现看起来不错;为什么不将其作为补丁提交到monad-loops 包?

【讨论】:

    【解决方案2】:

    好吧,我希望 iterateM 组合器具有这种类型签名:

    iterateM :: (Monad m) => (a -> m a) -> a -> m [a]
    

    当然,这不是一个非常有用的组合器,因为您无法在大多数 monad 中提取结果。 iterateM_:

    iterateM_ :: (Monad m) => (a -> m a) -> a -> m b
    iterateM_ f = fix $ \again x -> f x >>= again
    

    这个组合器很有用:

    countFrom :: (Enum a) => a -> IO b
    countFrom = iterateM_ (\x -> succ x <$ print x)
    

    但是,为了简单起见,我只会使用fix 或显式递归。显式递归代码并没有更长或更不可读:

    countFrom :: (Enum a) => a -> IO b
    countFrom = fix (\again x -> print x >> again (succ x))
    

    【讨论】:

    • 感谢您的提醒:这个名字——你是对的。也感谢您的示例!
    【解决方案3】:

    我相信您在标准库中看不到它的原因是它永远不会终止。 iterate 函数可以利用惰性列表来允许您在结果列表上使用 take 函数指定终止。在这里,你的结果是一元的,所以这是不可能的。

    显然你的想法的精神是可以做到的。它只是看起来有点不同:

    iterateM :: Monad m => Int -> (a -> m a) -> a -> m a
    iterateM 0 _ a = return a
    iterateM n f a = f a >>= iterateM (n-1) f
    

    【讨论】:

    • 确实如此,但用例也不同! (即我不希望它终止,就像forever 的用户一样。)
    • 当然也有例外和System.Exit,但这些通常不应该(ab)用于故意打破循环。
    • Len:啊,我明白了。我想只是使用你的定义。我不知道标准库中有什么这样做的。
    • 不能像(a -&gt; MaybeT m a) -&gt; a -&gt; m a 这样工作吗?
    • @leftaroundabout 嘿,我最近写了几乎完全一样的东西!请参阅github.com/DanBurton/bf-interp/blob/master/Program.hs 中的loopM——而不是return (),您可以使用return a 并获得您正在寻找的精确签名。
    【解决方案4】:

    这实际上可以用forever 写成StateT

    import Control.Monad.Trans.State
    import Control.Monad.Trans.Class (lift)
    import Control.Monad (forever)
    
    iterateM :: Monad m => (a -> m a) -> a -> m b
    iterateM f = evalStateT $ forever $ get >>= lift . f >>= put
    

    【讨论】:

    • 谢谢!这也澄清了我对lift 的一些看法。
    猜你喜欢
    • 2016-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-03
    相关资源
    最近更新 更多