So there are two uses of lenses in the `pipes` ecosystem: `pipes-parse`
and `pipes-group` (i.e. the `FreeT` stuff). What I was referring to was
the use of lenses in `pipes-group`. The rough rule of thumb for when to
use lenses in `pipes-group` is: pretty much always (i.e. every
"splitter" should be a lens).
I can also answer your question about when to use lenses in
`pipes-parse`, too. The answer is: if the transformation is reversible,
make it a lens. If the transformation is not reversible, make it a
function between `Producer`s (i.e. a "Getter", which is what it's
isomorphic to).
This is why `pipes-parse` is nothing but "Getter"s: none of the
transformations are reversible.
To learn more about this last point, read the `pipes-parse` tutorial,
particularly the section on `Getter`s:
http://hackage.haskell.org/package/pipes-parse-3.0.1/docs/Pipes-Parse-Tutorial.html#g:4
On 02/09/2014 05:01 PM, Pierre R wrote:
Is there any documentation about when it is not a good idea to define
`lens` ?
I am thinking about `pipes-attoparsec` that has chosen not to define any.
I know there is a thread that talk about this. It might be nice to
document this kind of argument.
If `lens` is not always the best approach (even for skilled lens
users), then I would move them in a separated module as Renzo
suggested (such as `Pipes.Parse.Lens` and I would document the pro and
cons there)
On Saturday, February 8, 2014 5:04:01 PM UTC+1, Gabriel Gonzalez wrote:
I got a couple of confused users upon the update to the lens-based
API,
mainly because it wasn't obvious to them how lenses worked and how to
use `view` to turn a `Lens a b` into `a -> b`. For example, they
didn't
realize that they could get back the original `decodeGetMany` by
using
`view decodeGetL`.
So I wanted to ask if there were any objections to me adding
unidirectional non-lens versions of several lenses. I think the
easiest
way to explain what I mean is to just give a few examples. Take
`Pipes.Parse.groupBy`, for example:
groupBy
:: Monad m
=> (a -> a -> Bool)
-> Lens' (Producer a m x) (Producer a m (Producer a m x))
groupBy equals k p0 = fmap join (k (to p0))
where
-- to :: Monad m => Producer a m r -> Producer a m (Producer
a m x)
to p = do
x <- lift (next p)
case x of
Left r -> return (return r)
Right (a, p') -> (yield a >> p') ^. span (equals a)
I'd probably take the internal `to` function and promote it to a
top-level exported function, named `groupBy_`:
groupBy_ :: Monad m => (a -> a -> Bool) -> Producer a m x ->
Producer a m (Producer a m x)
groupBy_ equals p = ...
Then define the `groupBy` lens in terms of `groupBy_`:
groupBy equals k p = fmap join (k (groupBy_ p))
Another example is the `lines` function from `Pipes.ByteString`:
lines
:: Monad m
=> Iso' (Producer ByteString m x) (FreeT (Producer
ByteString
m) m x)
lines = Data.Profunctor.dimap _lines (fmap _unlines)
where
-- _lines
-- :: Monad m
-- => Producer ByteString m x -> FreeT (Producer
ByteString
m) m x
_lines p0 = PG.FreeT (go0 p0)
where
go0 p = do
x <- next p
case x of
Left r -> return (PG.Pure r)
Right (bs, p') ->
if (BS.null bs)
then go0 p'
else return $ PG.Free $ go1 (yield bs >> p')
go1 p = do
p' <- p^.line
return $ PG.FreeT $ do
x <- nextByte p'
case x of
Left r -> return (PG.Pure r)
Right (_, p'') -> go0 p''
-- _unlines
-- :: Monad m
-- => FreeT (Producer ByteString m) m x -> Producer
ByteString m x
_unlines = concats . PG.maps addNewline
-- addNewline
-- :: Monad m => Producer ByteString m r -> Producer
ByteString m r
addNewline p = p <* yield (BS.singleton nl)
I'd promote `_lines` and `_unlines` to top-level exported functions,
except I would change the names to `lines_` and `unlines_`:
lines_ :: Monad m => Producer ByteString m x -> FreeT (Producer
ByteString m) m x
unlines_ :: Monad m => FreeT (Producer ByteString m) m x ->
Producer ByteString m x
... and define the `lines` lens in terms of them:
lines = Data.Profunctor.dimap lines_ (fmap unlines_)
So I would still be keeping the lenses and isomorphisms, but also
adding
unidirectional non-lens equivalents to give beginners an easier
toe-hold. What do you all think?
--
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].