gpt4 book ai didi

haskell - 如何在 monad 中懒惰地构建 Haskell 列表?

转载 作者:行者123 更新时间:2023-12-04 07:35:32 25 4
gpt4 key购买 nike

考虑以下两个几乎相同的函数:

buildList 0 = []
buildList n = n : buildList (n - 1)

buildListM 0 = return []
buildListM n = buildListM (n - 1) >>= return . (n :)

Haskell 的惰性方面允许 buildList生成列表而不会在内存中产生太多开销,因为它会生成列表的头部,然后构建尾部。

但是一元版本 buildListM似乎使用更多内存作为 n变大是因为它必须先构建尾部,然后再添加头部。

这是在 monad 中构建列表的好方法,还是有更有效的方法?

最佳答案

许多 Monads (例如, IO ,严格的 ST s ,严格的 State s )是“严格的”,因为 >>=其左操作数是严格的。其他,最值得注意的是 Identity还有(->) a , 懒惰 State s , 懒惰 Writer q , 懒惰 ST s , 在 >>= 的意义上是“懒惰的”其左操作数不严格。考虑申请toListMIdentity单子(monad):

buildListM 0 = return []
buildListM n = buildListM (n - 1) >>= return . (n :)

在这里, return = IdentityIdentity m >>= f = f m , 所以
buildListM 0 = Identity []
buildListM n = Identity . (n :) $ runIdentity (buildListM (n - 1))
= Identity (n : runIdentity (buildListM (n - 1)))

由于 IdentityrunIdentity在运行时完全无操作, buildListM实际上与 buildList 相同在 Identity 中运行时单子(monad)。使事情变得严格的是特定的单子(monad),而不是单子(monad)的本性。

您有时可以通过以下两种方式之一在“严格” monad 中做懒惰的事情:
  • 使用 unsafeInterleaveIO 作弊或 unsafeInterleaveST .
  • 使用更强大的MonadFix抽象,它可以让你在计算结果被执行之前掌握它,但是如果你在它可用之前访问这样的结果,那你就会失败。
  • 关于haskell - 如何在 monad 中懒惰地构建 Haskell 列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34270647/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com