Using the channel library, I want to write a program to read data from some source and copy it monoidally (say, using Sum ). The easiest way to do this is
import Control.Proxy as import Data.Monoid (Sum) main = do let source = enumFromToS (0::Int) 5 a <- runWriterT $ runProxy $ source >-> foldD Sum print a
Of course, although this works for small sources, large inputs will lead to a scary stack overflow due to the lazy nature of the WriterT battery.
Fortunately, pipes seem to be expecting this, providing the WriterP proxy with a strict battery. Unfortunately, the documentation surrounding this proxy is pretty scarce. After some conversation (and simplifying the problem, to instead accumulate 1 for each descending element), I came to this program,
import Control.Proxy import Control.Proxy.Trans.Writer import Data.Monoid (Sum) main = do let source = enumFromToS (0::Int) 5 a <- runProxy $ runWriterK $ source >-> \x->tell (Sum 1::Sum Int) print a
Of course, this program does not even perform the simplified task correctly, since it accumulates to 1 instead of 6. If I am not mistaken, this behavior is explained by the fact that the pipe only reads one element before terminating. To repeat to the end of the input, I came up with the following:
import Control.Proxy import Control.Proxy.Trans.Writer import Data.Monoid (Sum) main = do let source = enumFromToS (0::Int) 5 a <- runProxy $ runWriterK $ source >-> fold Sum print a fold :: (Monad m, Proxy p, Monoid w) => (a -> w) -> a' -> WriterP wpa' aa' amr fold f = go where go x = do a <- request x tell $ fa x' <- respond a go x'
This code, however, returns battery 0. Why is this? Is there a function like my fold in pipes ?
Given that many use cases for pipes are lengthy processes that work with large datasets, does it not make sense for folds in Control.Proxy.Prelude be built around strict WriterP instead of WriterT ? Currently, it seems that the proxy transformers in pipes are second-class citizens, are present, but do not have a large number of combinators that make WriterT so convenient.