Enumerators vs. Conduits或者是什么的利弊。管?

时间:2012-04-02 21:07:56

标签: haskell enumerators conduit

我想听听比我更深刻理解的人EnumeratorsConduitsPipes之间的根本区别以及主要的好处和缺点。一些discussion's already ongoing但是有一个高级概述会很高兴。

2 个答案:

答案 0 :(得分:28)

作为抽象的调查员/ Iteratees是由Oleg Kiselyov发明的。它们提供了一种干净的IO方式,可以预测(低)资源需求。目前的Enumerators包非常接近Oleg的原创作品。

为Yesod Web框架创建了管道。我的理解是它们的设计速度非常快。该图书馆的早期版本非常有状态。

管道专注于优雅。它们只有一种类型而不是几种,形成monad(变换器)和类别实例,并且在设计中非常“功能”。

如果您喜欢分类解释:Pipe类型只是免费的monad而不是以下不敬虔的简单仿函数

data PipeF a b m r = M (m r) | Await (a -> r) | Yield b r
instance Monad m => Functor (PipeF a b m) where
   fmap f (M mr) = M $ liftM mr
   fmap f (Await g) = Await $ f . g
   fmap f (Yield b p) = Yield b (f p)
--Giving:
newtype Pipe a b m r = Pipe {unPipe :: Free (PipeF a b m) r}
  deriving (Functor, Applicative, Monad)

--and
instance MonadTrans (Pipe a b) where
   lift = Pipe . inj . M

在实际的管道定义中,这些是烘焙的,但这个定义的简单性是惊人的。管道在操作(<+<) :: Monad m => Pipe c d m r -> Pipe a b m r -> Pipe a d m r下形成一个类别,它接受第一个管道yields并将其提供给等待的第二个管道。

看起来Conduits正在变得更像Pipe(使用CPS而不是状态,并切换到单一类型),而Pipes正在获得对更好的错误处理的支持,也许返回发电机和消费者的不同类型。

这个地区正在迅速发展。我一直在使用具有这些功能的管道库的实验变体进行攻击,并且知道其他人也是如此(请参阅Hackage上的Guarded Pipes包),但怀疑Gabriel(Pipes的作者)会在我之前解决它们做。

我的建议:如果您使用Yesod,请使用Conduits。如果您想要一个成熟的库,请使用Enumerator。如果您主要关心优雅,请使用Pipe。

答案 1 :(得分:7)

在用所有三个库编写应用程序之后,我认为我看到的最大区别在于如何处理资源最终化。例如,Pipes将资源最终化分解为不同类型的Frames和Stacks。

关于如何不仅最终确定输入资源,而且可能还有输出资源,似乎还存在一些争论。例如,如果您正在从DB读取并写入文件,则需要关闭DB的连接以及需要刷新和关闭的输出文件。在决定如何处理管道中的异常和故障情况时,事情会变得很糟糕。

另一个更微妙的区别似乎是如何处理和计算枚举器管道的返回值。

许多这些差异和潜在的不一致性已经通过使用管道的Monad和类别实现而暴露出来,现在正在进入管道。