Lenses are a key aspect of `pipes-parse`. Asking for a lens-free subset of `pipes-parse` in order to avoid using lenses is analogous to asking for a `Pipe`-free subset of `pipes` in order to avoid using the `(>->)` operator.

I truly believe lenses should be the sole API for `pipes-parse`. Also, `lens-family-core` is a really tiny dependency, so I don't feel bad about asking users to depend on it to use `pipes-parse`.

However, the use of lenses for `pipes-group` (i.e. the `FreeT` lenses) is not strictly necessary and is only for code reuse. So if you want I can propose a compromise: keep `pipes-parse` lenses, add the `debugXXX` functions, and add the following non-lens versions of `pipes-group` functions:

* For all `FreeT` lenses, provide the `view` (i.e. the splitter)

* For all `FreeT` isomorphisms, provide the reverse view (i.e. the joiner) if it's not already in the API (example: `unlines`)

On 02/12/2014 06:34 PM, Kyle Van Berendonck wrote:
I thought I had already replied to this, but I must have forgotten to get back and post it.

I dislike this solution because it's forcing people into doing things they don't want to do. You don't need to provide all three; view, zoom and over -- that's un-necessary because if people need those they can just use the lenses, but you do need to provide a "complete" API so that someone can actually build a simple program with the option to extend it later with lenses when they feel more comfortable.

This means for example, `view decoded` is an important skeleton to provide and so is `encoder`.

Adding these debugging functions may fix the problem, but the solution is not the correct one. It's putting a lot of pressure on the user to feel that these errors are as a fault of them not being able to deal with the types produced by the libraries, rather than the more correct opinion that the libraries have made lens (an extension for seasoned users) the sole API, which (IMO) is wrong.

Regards.

On Tuesday, February 11, 2014 4:42:42 PM UTC+11, Gabriel Gonzalez wrote:

    Ok, I think I found an approach that will satisfy everybody.  This
    solution only requires providing three utility functions in
    `pipes-parse`:

        debugView
            :: (Producer a m x -> Producer b m y)
            -> (Producer a m x -> Producer b m y)
        debugView = id

        debugZoom
            :: (StateT (Producer a m x) m r -> StateT (Producer b m y)
    m r)
            -> (StateT (Producer a m x) m r -> StateT (Producer b m y)
    m r)
        debugZoom = id

        debugOver
            :: (   (Producer a m w -> Producer b m x)
                -> (Producer c m y -> Producer d m z) )
            -> (   (Producer a m w -> Producer b m x)
                -> (Producer c m y -> Producer d m z) )
        debugOver = id

    The following example shows how you would use it (see the `p3`
    example):

    http://lpaste.net/99760

    Notice how the type error is actually even *better* now than the
    "intermediate function" proposal.

    There also need to be equivalent type-restriction functions for
    `FreeT` transformations as well.  Those will go in `pipes-group`.

    The nice advantages of this solution are:

    * There's no longer a need to provide three extra functions for
    every lens (i.e. one each for `view`/`zoom`/`over`)

    * The user doesn't need to know what the restricted type should
    be.  The utility functions take care of that.

    * It's very easy to undo once the user has found the correct type,
    by deleting the `debugXXX` function.  This leaves the user with
    idiomatic lens-based code.

    On 02/10/2014 02:51 PM, Kyle Van Berendonck wrote:
    I don't think teaching users how to "hack around" the titanic
    type error issue is really a solution though, and certainly not
    in pipes-parse because people who are interested in a particular
    pipes library are less likely to read it there.

    On Monday, February 10, 2014 3:28:13 AM UTC+11, Gabriel Gonzalez
    wrote:

        So I was thinking some more about this, and I was wondering
        if perhaps the solution would be to simply explain in the
        `pipes-parse` tutorial how to simplify type errors using the
        trick of defining an intermediate non-lens function.

        The tutorial would say (in more words) that if you have a
        type error with a `lens` of type `Lens (Producer a m x)
        (Producer b m y)` while using `view`, then you should convert
        it to an intermediate ordinary function like this:

            intermediate :: Producer a m x -> Producer b m y
            intermediate = view lens

        ... then use that `intermediate` function for better type
        error inference.  Similarly, if you have a type error using
        the `lens` with a `zoom`, then you convert it to the
        following intermediate ordinary function:

            intermediate:: StateT (Producer b m y) m r -> StateT
        (Producer a m x) m r
            intermediate = zoom lens

        Teaching beginners how to do this would help them improve
        type errors without having to add redundant functions to the API.

-- 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] <javascript:>.
    To post to this group, send email to [email protected]
    <javascript:>.

--
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].

Reply via email to