2012-04-02 86 views

回答

28

作为抽象的统计员/迭代者是由Oleg Kiselyov发明的。它们提供了一种干净的方式来执行可预测(低)资源需求的IO。目前的统计员包非常接近Oleg的原始工作。

管道是为Yesod网络框架创建的。我的理解是,他们的设计非常快。早期版本的库是高度有状态的。

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

如果你喜欢分类解释:Pipe类型只是在接下来的恶人简单仿

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而不是状态,并切换到单一类型),而管道正在获得更好的错误处理的支持,也许发电机和消费者返回不同类型。

该地区正在迅速发展。我一直在使用具有这些功能的Pipe库的实验变体,并且知道其他人也是如此(请参阅Hackage上的Guarded Pipes软件包),但怀疑Gabriel(Pipes的作者)会在我做。

我的建议:如果您使用Yesod,请使用导管。如果你想让一个成熟的库使用枚举器。如果您主要关心优雅,请使用管道。

7

在与所有三个库一起编写应用程序之后,我认为我看到的最大差异是如何处理资源最终化。例如,Pipes将资源定稿分解为不同类型的框架和堆栈。

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

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

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