当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何懒惰地在monad中构建Haskell列表?》经验,为你挑选了1个好方法。

考虑以下两个几乎相同的功能:

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

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

Haskell的懒惰方面允许buildList在内存中生成列表而没有太多开销,因为它生成列表的头部然后构建尾部.

但monadic版本buildListM似乎使用更多的内存,n因为它必须首先构建尾部然后在头部前面.

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



1> dfeuer..:

许多Monads(例如,IO严格ST s,严格State s)是"严格的",因为>>=它的左操作数是严格的.其他的,最主要的是Identity(->) a,懒State s,懒Writer q,懒ST s,在这个意义上,"懒" >>=是不是在它的左操作数严格.考虑申请toListMIdentity单子:

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)))

由于Identity并且runIdentity在运行时完成无操作,buildListM实际上与buildListIdentitymonad中运行时相同.特别是monad,而不是monadic性质,使事情变得严格.

你有时可以用两种方式之一在"严格"的monad中做懒惰的事情:

    使用unsafeInterleaveIO或作弊unsafeInterleaveST.

    使用更强大的MonadFix抽象,它可以让你在执行之前掌握计算结果,但是如果你在可用之前访问这样的结果,那将会失败.

推荐阅读
依然-狠幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有