I managed to convert between `P.Producer (ZipList a) m r` and `ZipList
(P.Producer a m ()` using the StateT trick used in Pipes.Parse
Does the following code make sense? Am I breaking any laws?
import Control.Applicative
import Control.Monad.Trans.Class
import Control.Monad.Trans.State.Strict
import qualified Pipes as P
import qualified Pipes.Lift as PL
-- ZipList Traversable is only in 4.9.0.0
sequenceAZipList :: Applicative f => ZipList (f a) -> f (ZipList a)
sequenceAZipList xs = ZipList <$> sequenceA (getZipList xs)
-- | Similar to Pipes.Parse.Parser, except it stores a ZipList of Producers.
type ZipParser a m r = forall x . StateT (ZipList (P.Producer a m x)) m r
-- | Draw one element from each underlying Producer, returning 'Nothing' if
any of the producers are empty
drawZ :: Monad m => ZipParser a m (Maybe (ZipList a))
drawZ = do
ps <- get
rs <- lift (sequenceAZipList (P.next <$> ps))
case sequenceAZipList rs of
Left _ -> pure Nothing
Right rs' -> do
put $ snd <$> rs'
pure . Just $ fst <$> rs'
-- | Push back a Ziplist element onto the underlying ZipList of Producers
unDrawZ :: Monad m => ZipList a -> ZipParser a m ()
unDrawZ as = modify (\ps -> appendA <$> ps <*> as)
where
appendA p a = do
r <- p
P.yield a
pure r
toZipList :: Monad m => P.Producer (ZipList a) m r -> m (ZipList
(P.Producer a m ()))
toZipList p = execStateT (toZipParser p) (pure (pure ()))
where
toZipParser :: Monad m => P.Producer (ZipList a) m r -> ZipParser a m r
toZipParser p' = do
r <- lift $ P.next p'
On Tuesday, 23 August 2016 15:01:54 UTC+10, Louis Pan wrote:
>
> Sorry, could you please elaborate? I'm a bit slow.
>
> How do I use Control.Foldl.Fold to convert `Pipes a b m r` into `Pipes
> (ZipList a) (ZipList b) m r` ?
>
>
> On Tuesday, 23 August 2016 13:20:24 UTC+10, Gabriel Gonzalez wrote:
>>
>> I would do what you're already doing with `Control.Foldl.Fold`. That's
>> the approach I usually recommend for this.
>>
>> On Aug 22, 2016, at 6:45 PM, Louis Pan <[email protected]> wrote:
>>
>> One approach I can think of is the use Pipes.Concurrent to manually split
>> the ZipList and then combine then results. Is there a nicer way?
>>
>> On Tuesday, 23 August 2016 11:35:50 UTC+10, Louis Pan wrote:
>>>
>>> Say I have a `Pipes a b m r` called 'p'.
>>>
>>> How do I convert it to a `Pipes (ZipList a) (ZipList b) m r`?
>>> That is, I want to apply the pipe 'p' and apply zip-wise to an input
>>> ziplist, without losing the state of each pipe in the ziplist.
>>>
>>> The reason I want this, is that I want to run multiple attoparsec
>>> parsers in parallel in one pass of a file.
>>>
>>> My approach for this is to use Control.Foldl to combine the attoparsec
>>> parsers into a `Control.Foldl.Fold ByteString [PartialParseResult]`, then
>>> convert it (using Control.Foldl.purely Pipes.Prelude.scan) to a `Pipe
>>> ByteString [PartialParseResult]`
>>>
>>> My other requirement is that I want to look at intermediate parser
>>> output (eg. each line of a file as it's parsed), in order to summarise each
>>> line, in a stateful way as I'm keeping track of the current line number.
>>>
>>> My approach for this is to use Control.Foldl.Fold for the summary logic,
>>> and then convert it to a pipe. I am able to create a `Pipe
>>> PartialParseResult AnalysisResult m r` for this.
>>>
>>> However, how do I connect a `Pipe ByteString [PartialParseResult] m r`
>>> to a `Pipe PartialParseResult AnalysisResult m r`?
>>>
>>> Regards,
>>>
>>> Louis
>>>
>>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "Haskell Pipes" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> To post to this group, send email to [email protected].
>>
>>
>>
--
You received this message because you are subscribed to the Google Groups
"Haskell Pipes" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].