调查员与管道与管道的利弊是什么?

Luk*_*ten 34 haskell enumerators conduit

我想从别人有更深的了解比我的根本区别是什么之间听到普查员,管道管道以及主要优点和缺点.一些讨论已经 在进行中,但有一个高级概述是很好的.

Phi*_* JF 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
Run Code Online (Sandbox Code Playgroud)

在实际的管道定义中,这些是烘焙的,但这个定义的简单性是惊人的.管道在操作下形成一个类别,(<+<) :: 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.


Luk*_*ten 7

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

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

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

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