You are here

Conduits are not Monads

Pipes from the conduit package on hackage have a Monad instance that violates the monad laws.
> import Data.Conduit (Pipe(Done), ($$), (=$))
> import Data.Conduit.List (sourceList, map, consume)
> import Data.Functor.Identity (runIdentity)
> import Control.Monad ((>=>))

This is a perfectly good Pipe / Conduit / Source
> inject = flip Done () . Just

> pipefns :: (Num o, Monad m) => [() -> Pipe o o m ()]
> pipefns = [const $ inject 1, const $ inject 0, const $ Data.Conduit.List.map id]

> lassoc = foldl1 (>=>) pipefns
> rassoc = foldr1 (>=>) pipefns

> run cf = runIdentity $ sourceList [2..5] $$ cf undefined =$ consume

> main = do
>     print $ run lassoc
>     print "/="
>     print $ run rassoc
Be careful how you compose Pipes that "push back" some input.