Каковы плюсы и минусы счетчиков против трубопроводов против труб? - PullRequest
33 голосов
/ 03 апреля 2012

Я хотел бы услышать от кого-то с более глубоким пониманием, чем я, в чем принципиальные различия между счетчиками , кабелепроводами и трубами , а также Ключевые преимущества и недостатки. Некоторое обсуждение уже продолжается , но было бы неплохо иметь общий обзор.

Ответы [ 2 ]

28 голосов
/ 03 апреля 2012

Перечислители / Итераторы как абстракция были изобретены Олегом Киселевым. Они обеспечивают чистый способ выполнения ввода-вывода с предсказуемыми (низкими) требованиями к ресурсам. Текущий пакет Enumerators довольно близок к оригинальной работе Олега.

Были созданы проводники для веб-фреймворка Yesod. Насколько я понимаю, они были разработаны, чтобы быть невероятно быстрым. Ранние версии библиотеки были очень полными.

Трубы нацелены на элегантность. Они имеют только один тип вместо нескольких, образуют экземпляры монад (трансформеров) и категорий и очень «функциональны» в дизайне.

Если вам нравятся категоричные объяснения: тип 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 с этими функциями, и знаю, что другие люди тоже (см. Пакет Guarded Pipes на Hackage), но подозреваю, что Габриэль (автор Pipes) выяснит их, прежде чем я делать.

Мои рекомендации: если вы используете Yesod, используйте Conduits. Если вы хотите зрелую библиотеку, используйте Enumerator. Если вы в первую очередь заботитесь об элегантности, используйте Pipe.

7 голосов
/ 16 июля 2012

После написания приложений для всех трех библиотек, я думаю, самое большое различие, которое я видел, заключается в том, как обрабатывается финализация ресурсов.Например, Pipes разбивает финализацию ресурса на отдельные типы фреймов и стеков.

По-прежнему, похоже, идут споры о том, как завершить не только входной, но и потенциально выходной ресурс.Например, если вы читаете из БД и записываете в файл, соединение с БД должно быть закрыто, а выходной файл должен быть очищен и закрыт.При решении вопроса о том, как обрабатывать исключения и случаи сбоев вдоль конвейера, дела идут не так, как надо.

Другое, более тонкое отличие, похоже, заключается в том, как обрабатывается и вычисляется возвращаемое значение конвейера перечислителя.

Многоиз этих различий и потенциальных несоответствий были выявлены при использовании реализаций Monad и Category для Pipes, и теперь они пробиваются в Conduits.

...