Pipes.Parse lenses

82 views
Skip to first unread message

Thomas Wilkinson

unread,
Mar 6, 2016, 9:06:40 AM3/6/16
to Haskell Pipes
I am slightly freaked out by the `Lens`es provided by `Pipes.Parse` being 'improper'.  Could they not be `Getter`s instead?

    type Splitter a m = forall x. Getter (Producer a m x) (Producer a m (Producer a m x))
    -- Should have   " join . view sp == id "     for any sp :: Splitter a m  and  p :: Producer a m r

    span :: Monad m => (a -> Bool) -> Splitter a m
    splitAt :: Monad m => Int -> Splitter a m
    groupBy :: Monad m => (a -> a -> Bool) -> Splitter a m
    group :: (Monad m, Eq a) => Splitter a m

    -- would replace `zoom`
    split :: Splitter a m -> Parser a m r -> Parser a m r
    split sp st = StateT $ \p -> fmap (fmap join) (runStateT st (p^.sp))

This means that users would sometimes have to use `zoom` and sometimes have to use `split`, which might be annoying.  But it feels better than having fake `Lens`es somehow.

Gabriel Gonzalez

unread,
Mar 6, 2016, 11:14:21 AM3/6/16
to haskel...@googlegroups.com
I would prefer to keep them the way they are, because the full `Lens` functionality isn’t used just for `zoom` but also for other utilities like `over` or `set`.  It’s easier to just warn users that a lens is improper than to create parallel versions of every utility that a person might want to use with these `Lens`es.

--
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 haskell-pipe...@googlegroups.com.
To post to this group, send email to haskel...@googlegroups.com.

Thomas Wilkinson

unread,
Mar 6, 2016, 11:31:52 AM3/6/16
to Haskell Pipes
Do you sometimes need to `set (span even)` or `set group`?  When is that helpful?

Tom Ellis

unread,
Mar 6, 2016, 12:17:37 PM3/6/16
to Haskell Pipes
On Sun, Mar 06, 2016 at 06:06:40AM -0800, Thomas Wilkinson wrote:
> I am slightly freaked out by the `Lens`es provided by `Pipes.Parse` being
> 'improper'. Could they not be `Getter`s instead?
>
> type Splitter a m = forall x. Getter (Producer a m x) (Producer a m
> (Producer a m x))
> -- Should have " join . view sp == id " for any sp :: Splitter a
> m and p :: Producer a m r
>
> span :: Monad m => (a -> Bool) -> Splitter a m
> splitAt :: Monad m => Int -> Splitter a m
> groupBy :: Monad m => (a -> a -> Bool) -> Splitter a m
> group :: (Monad m, Eq a) => Splitter a m
>
> -- would replace `zoom`
> split :: Splitter a m -> Parser a m r -> Parser a m r
> split sp st = StateT $ \p -> fmap (fmap join) (runStateT st (p^.sp))

In case anyone, like me, was interested in the fully general version of
this here it is:

split :: (Monad m, Functor n)
=> Getting (m (m a)) (m a) (m (m a))
-> StateT (m (m a)) n r -> StateT (m a) n r
split sp st = StateT $ \p -> fmap (fmap join) (runStateT st (p^.sp))

I suspect one could make Parser a newtype and then add a Zoomed instance to
make zoom work with the Getters above, but I haven't checked (not that I am
claiming that is a desirable thing for the pipes-parse API, merely that it
might be possible).

Tom



Gabriel Gonzalez

unread,
Mar 12, 2016, 2:52:01 PM3/12/16
to haskell-pipes, thomas.s....@gmail.com
Here are some examples of things you can do by reusing the lens machinery:

    -- Insert a 1 after the 5th element
    over (Pipes.Parse.splitAt 5) (<* yield 1)

    -- Replace the first group of consecutive matching elements with 1
    set (Pipes.Parse.group . Pipes.Extras.output) 1

    -- Replace each line with "FOO"
    over (Pipes.ByteString.lines . Pipes.Group.individually) (\p -> yield "FOO" >> for p discard)

Thomas Wilkinson

unread,
Mar 12, 2016, 3:10:30 PM3/12/16
to Haskell Pipes, thomas.s....@gmail.com
OK, I'm convinced!  That looks very useful.  :)
Reply all
Reply to author
Forward
0 new messages