【问题标题】:How can I run multiple Haskell IO actions and store the results?如何运行多个 Haskell IO 操作并存储结果?
【发布时间】:2018-03-30 17:08:28
【问题描述】:

我是 Haskell 初学者,对于新手问题,我深表歉意。我对monads的理解很肤浅。

我正在使用 Persistent 模块中的函数 insert。 (我一直关注the tutorial here。)它在数据库中插入一些东西,并返回ID。我可以这样使用它:

resultId <- insert myItem

这适用于单个项目。我可以像这样打印出 resultId:

liftIO $ print resultId

但是如果我的myItem 实际上是一个任意长度的列表呢?我想在这个列表上映射insert,我似乎可以这样做:

resultIds <- mapM_ insert myItemList

但是如果我尝试打印出这些值:

liftIO $ print resultIds

我刚收到()。我究竟做错了什么?

【问题讨论】:

  • 您应该使用mapM 而不是mapM_ 下划线表示您不关心结果。
  • 酷,谢谢,成功了。
  • 详细说明,mapM_ 丢弃结果,将其替换为()。它在某些情况下很有用,但当然不是在这里。

标签: haskell


【解决方案1】:

你很接近:你需要mapM :: Monad m =&gt; (a -&gt; m b) -&gt; t a -&gt; m (t b)而不是mapM_ :: (Foldable t, Monad m) =&gt; (a -&gt; m b) -&gt; t a -&gt; m ()

就像名称和签名已经暗示的那样,这两个函数都采用一个单子函数和一个可遍历的as(让我们现在假设这是一个列表),并将单子函数应用于所有元素并返回包含结果的可遍历(列表)的一元函数。

所以如果你写:

    resultIds &lt;- <b>mapM</b> insert myItemList

mapMmapM_ 之间的区别在于,在mapM_ 的情况下(就像签名已经暗示的那样),您对结果不感兴趣,因此不计算。造成这种情况的原因可能是列表很长(并且根据需要生成),因此标识符列表永远无法放入内存。

那么resultIds 将包含一个标识符列表。

关于mapM(和mapM_)函数的解释有点过于简单化了,但我认为首先了解monads通常比完全正确地了解monadic函数的细节要好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多