For people who haven't been following this discussion on Github, I'm
paraphrasing the answer I gave here:
https://github.com/k0001/pipes-binary/issues/12#issuecomment-34539242
For `decoded` (and similar lenses with error continuation return values)
the additional power of an `Iso` is more trouble than its worth. For
example, given an `Iso` like:
Iso' (Producer a m r) (Producer b m (Either (SomeError ...) ...))
... the user wouldn't be able to use the reverse direction unless they
first fixed the return value to be an `Either`. The only case where the
return value is already going to be in the correct form is if they just
decoded it using the same `Iso'`, but in those cases you don't need
something as powerful as an `Iso'`, because you can just use `over`,
which only requires a `Lens`. For example, let's say I wanted to decode
a stream of `Int`s, increment all of them, and then re-encode them. I
would just write:
over decoded (>-> Pipes.Prelude.map ((+1) :: Int -> Int))
:: Monad m => Producer ByteString m r -> Producer ByteString m r
That only requires a `Lens` and not an `Iso`.
Note that not all such transformations can be expressed in terms of
`over`. For example, you can't use `over` to take the first N decoded
ints this way (because the re-encoded result must have the same return
value). For these cases, the idiomatic solution I recommend is to use
`encoder`, which is just `for cat encode`:
example = view decoded someByteStream >-> Pipes.Prelude.take 5 >->
encoder
encoder :: (Monad m, Binary a) => Pipe a ByteString m r
encoder = for cat encode
-- ... plus some shortcut fusion rules
I just submitted a pull request for `encoder` here:
https://github.com/k0001/pipes-binary/pull/15
In this case I definitely think that `decoded` should not be a `Getter`
and should stay at least a `Lens`. The reversibility is good enough for
most purposes and you don't really need the `Iso` to re-encode things.
Also, `zoom decoded` and `over decoded` are too useful to give up.
However, I was planning on suggesting providing non-lens versions of
many lenses for beginners. I will discuss this in a separate thread.
On 02/08/2014 09:50 PM, Danny Navarro wrote:
While discussing whether `decoded` in `pipes-binary` should be an
`Iso'` a `Getter'` or a `Lens'` [1], I started thinking what would be
the advantages of each one from the parsing point of view.
The obvious advantage of the `Iso'` would be that it's automatically
reversible using `from`[2], so you get `encoded` for free. But it
turns out it's not truly reversible when facing errors, `lens-family`
doesn't include the `from` function and it's in the end not that
obvious to use for end users.
Using `Lens'`es for `decoded` and `encoded` raises the question that
if we are considering the lenses irreversible, why not just use
`Getter'`s? They wouldn't violate the lens laws and could be composed
correctly with other lenses, folds, traversals..., when applicable.
After all, if we have `Getter`s that transform `Producer`s as we need,
what's the use of the *setter* part of a `Producer` lens?
Well, it turns out that `zoom` can't use `Getter`s [3], but I fail to
understand how it uses the *setter* part, changing what the *setter*
does, doesn't seem to affect `zoom`. There is also `magnify` which
works like `zoom` with `Getter`s but it can't operate on the state
monad [4].
So I was thinking why not include a version of `zoom` in `pipes-parse`
that works with `Getter`s, using `mapStateT` for example [5], and base
all pipes parsing on `Getter`s by default? What would be the
disadvantages of this approach?
[1] https://github.com/k0001/pipes-binary/issues/12
[2]
http://hackage.haskell.org/package/lens-4.0.1/docs/Control-Lens-Iso.html#v:from
[3]
http://hackage.haskell.org/package/lens-4.0.1/docs/Control-Lens-Zoom.html#v:zoom
[4]
http://hackage.haskell.org/package/lens-4.0.1/docs/Control-Lens-Zoom.html#v:magnify
[5]
http://hackage.haskell.org/package/transformers-0.3.0.0/docs/Control-Monad-Trans-State-Strict.html#v:mapStateT
-- Danny Navarro
--
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].