Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell:在monad transformer堆栈中替换mapM以实现惰性评估(无空间泄漏)_Haskell_Monads_Lazy Evaluation_Monad Transformers - Fatal编程技术网

Haskell:在monad transformer堆栈中替换mapM以实现惰性评估(无空间泄漏)

Haskell:在monad transformer堆栈中替换mapM以实现惰性评估(无空间泄漏),haskell,monads,lazy-evaluation,monad-transformers,Haskell,Monads,Lazy Evaluation,Monad Transformers,已经讨论过,mapM本质上不是懒惰的,例如和。现在我正在努力解决这个问题的一个变体,其中所讨论的mapM位于monad转换器堆栈的深处 下面是一个函数,它取自一个使用LevelDB的具体工作(但空间泄漏)示例: 一种解决方案是使用流媒体库,如管道,管道,等等。但这些库似乎相当繁重,我根本不知道在这种情况下如何使用它们 我研究的另一个路径是所建议的ListT。但是ListT.fromFoldable::[Bool]->ListT-Bool和ListT.fold::(r->a->mr->tma->m

已经讨论过,
mapM
本质上不是懒惰的,例如和。现在我正在努力解决这个问题的一个变体,其中所讨论的
mapM
位于monad转换器堆栈的深处

下面是一个函数,它取自一个使用LevelDB的具体工作(但空间泄漏)示例:

一种解决方案是使用流媒体库,如
管道
管道
,等等。但这些库似乎相当繁重,我根本不知道在这种情况下如何使用它们

我研究的另一个路径是所建议的
ListT
。但是
ListT.fromFoldable::[Bool]->ListT-Bool
ListT.fold::(r->a->mr->tma->mr
(其中
m
=
IO
a
r
=
Bool
)的类型签名与当前问题不匹配

什么是消除空间泄漏的“好”方法

更新:请注意,此问题与monad transformer堆栈无关!以下是建议解决方案的摘要:

1) 使用
流媒体

import Streaming
import qualified Streaming.Prelude as S
S.all_ id (S.mapM check' (S.each [1..n]))
2) 使用
Control.Monad.foldM

foldM (\a i-> do {b<-check' i; return $! a && b}) True [1..n]

我知道您提到您不想使用流媒体库,但是您的问题似乎很容易解决,而且代码也没有太多更改

import Streaming
import qualified Streaming.Prelude as S
我们使用
每个[1..n]
而不是
[1..n]
来获得元素流:

each :: (Monad m, Foldable f) => f a -> Stream (Of a) m ()
流式处理纯可折叠容器的元素

(我们也可以编写类似于
S.take n$S.enumfrom1
)的代码

我们使用而不是
mapmcheck'

mapM :: Monad m => (a -> m b) -> Stream (Of a) m r -> Stream (Of b) m r
用一元操作的结果替换流的每个元素

然后我们用以下方法来折叠布尔语流:

总而言之:

S.all_ id (S.mapM check' (S.each [1..n]))

与您开始使用的代码没有太大区别,并且不需要任何新的操作员。

我知道您提到您不想使用流媒体库,但您的问题似乎很容易解决,无需对代码进行太多更改

import Streaming
import qualified Streaming.Prelude as S
我们使用
每个[1..n]
而不是
[1..n]
来获得元素流:

each :: (Monad m, Foldable f) => f a -> Stream (Of a) m ()
流式处理纯可折叠容器的元素

(我们也可以编写类似于
S.take n$S.enumfrom1
)的代码

我们使用而不是
mapmcheck'

mapM :: Monad m => (a -> m b) -> Stream (Of a) m r -> Stream (Of b) m r
用一元操作的结果替换流的每个元素

然后我们用以下方法来折叠布尔语流:

总而言之:

S.all_ id (S.mapM check' (S.each [1..n]))
与您开始使用的代码没有太大区别,并且不需要任何新操作符。

我认为您需要的是monad loops包

然后就是
allM-check'[1..n]

(或者,如果您不想导入,那么复制它是一个非常小的函数。)

我认为您需要的是monad loops包

然后就是
allM-check'[1..n]


(或者,如果您不想导入,那么复制它是一个非常小的函数。)

除了我给出的答案之外,如果您使用
控件中的普通正则
foldM
,会发生什么?似乎您也可以避免以这种方式具体化列表。我只是在这里尝试:
foldM(\a I->do{b@mcmayer,请尝试使用
返回$!a&&b
(当前
foldM
在计算前返回类似
(…&&True)&&True)&&True的thunk)。如果这不能解决问题,我想你可能是误判了泄漏。@luqui是的,
return$!a&&b
确实有效!没有空间泄漏。除了我给出的答案之外,如果你使用
Control.Monad
中的普通的
foldM
,会发生什么?似乎你也可以避免以这种方式实现列表。我刚刚尝试了这个回复:
foldM(\a i->do{b@mcmayer,请尝试使用
返回$!a&&b
(当前
foldM
在计算前返回类似
(…&&True)&&True)&&True的thunk)。如果这不能解决问题,我想你可能是误判了泄漏。@luqui是的,
返回$!a&&b
确实有效!没有空间泄漏。是的,这样做了!是的,这样做了!这是迄今为止最简单的解决方案!这是迄今为止最简单的解决方案!