我正在使用一个特定的数据库,在成功查询后,您可以使用特定命令访问一组结果数据块:
getResultData :: IO (ResponseCode, ByteString)
现在getResultData将返回一个响应代码和一些数据,其中响应代码如下所示:
response = GET_DATA_FAILED | OPERATION_SUCCEEDED | NO_MORE_DATA
ByteString是一个、一些或所有块:
故事并没有在这里结束。存在组流:
一旦从getResultData接收到NO_MORE_DATA响应,对getNextItem的调用将迭代流,允许我再次启动对getResultData的调用。一旦getNextItem返回STREAM_FINISHED,这就是她所写的全部内容;我有数据。
现在,我想用任何一种日期来重塑这种现象。Iteratee或Data。枚举器。因为我的现有数据。Iteratee解决方案工作,但它似乎非常天真,我觉得我应该用嵌套的可迭代对象来建模,而不是一个大的可迭代对象blob,这就是我的解决方案目前的实现方式。
我一直在看数据的代码。Iterateewww.example. www.example.com ,当涉及到嵌套的东西时,我有点困惑。
嵌套的迭代对象是正确的操作过程吗?如果是这样的话,如何用嵌套的可迭代对象来建模呢?
问候
1条答案
按热度按时间ncecgwcz1#
我认为嵌套的可迭代对象是正确的方法,但是这个例子有一些独特的问题,使它与大多数常见的例子略有不同。
分块和分组
第一个问题是正确的数据源。基本上,您所描述的逻辑划分将给予您一个等价于
[[ByteString]]
的流。如果您创建一个枚举器来直接产生这个,那么流中的每个元素都将是一个完整的块组,这可能是您希望避免的(出于内存原因)。您可以将所有内容扁平化为一个[ByteString]
,但这样就需要重新引入边界,这将是非常浪费的,因为数据库正在为您做这件事。现在先忽略组流,看起来您需要自己将数据划分成块。我将其建模为:
由于块的大小是固定的,因此可以使用
Data.Iteratee.group
轻松地将其分块。将此类型与
Enumerator
进行比较因此,
enumGroupChunked
基本上是一个奇特的枚举器,它可以更改流类型。这意味着它接受一个[ByteString]迭代者消费者,并返回一个消费普通字节串的迭代者。枚举数的返回类型通常并不重要;它只是一个迭代对象,你可以用run
(或tryRun
)来计算输出,所以你可以在这里做同样的事情:如果您需要对每个组进行更复杂的处理,那么最简单的地方就是
enumGroupChunked
函数。群组流
现在这是出路,该怎么办的群体流?答案取决于你想如何使用它们。如果你想独立处理流中的每个组,我会做类似的事情:
但是,假设您希望对整个数据集进行某种流处理,而不仅仅是单个组。也就是说,你有一个
你想在整个数据集上运行。这就是枚举数的返回可迭代对象的用处所在。一些早期的代码现在将略有不同:
这种嵌套的可迭代体(i.例如
Iteratee s1 m (Iteratee s2 m a)
)有点不常见,但当您希望顺序处理来自多个Enumerator的数据时,它特别有用。关键是要认识到run
外部迭代器将给予您一个准备好接收更多数据的迭代器。在这种情况下,这是一个很好的模型,因为您可以独立地枚举每个组,但将它们作为单个流进行处理。一个警告:内部被迭代者将处于其被保留的任何状态。假设组的最后一个块可能小于完整块,e.g的。
在这种情况下,由于
group
将数据组合成大小为1024的块,因此它将合并组A的最后一个块和组B的前512个字节。这在foldStream
示例中不是问题,因为该代码终止了内部被迭代者(使用joinI
)。这意味着这些组是真正独立的,所以你必须这样对待它们。如果你想像procStream
那样合并这些组,你必须考虑整个流。如果是这种情况,那么您需要使用比group
更复杂的东西。数据。迭代对象vs数据。枚举器
在不讨论任何一个包的优点的情况下,更不用说IterIO了(我承认我有偏见),我想指出我认为两者之间最重要的区别:流的抽象。
在Data.Iteratee中,使用者
Iteratee ByteString m a
对某个长度的概念性ByteString进行操作,同时可以访问ByteString
的单个块。在Data.Enumerator中,消费者
Iteratee ByteString m a
对概念性的[ByteString]进行操作,可以同时访问一个或多个元素(字节串)。这意味着大多数数据。迭代对象操作是以元素为中心的,也就是说,对于
Iteratee ByteString
,它们将在单个Word8
上操作,而Data。枚举器操作是以块为中心的,在ByteString
上操作。Data.Iteratee.Iteratee [s] m a
==Data.Enumerator.Iteratee s m a
。