r/haskell•
glguy

Lens 4.4 release notes

There's a new release of the lens package tonight, and I'd like to break down some of the changes from the changelog.

http://hackage.haskell.org/package/lens

Template Haskell changes

The Template Haskell module has been around through many revisions of the lens package and seen a lot of features added to it. There were multiple implementations of the same functionality in the module doing slightly different things and it was becoming a challenge to fix bugs or add functionality. To improve this situation the TH code has been rewritten and unified.

  • The common cases of makeLenses and makePrisms should continue to work as before.

  • There's a new makeClassyPrisms function to complement the makeClassy lens generating code. You can read more about this feature in the haddocks!

  • Lenses generated for a single constructor now use irrefutable patterns. This allows you to initialize an undefined with lenses.

  • The makeFields implementation is now merged into the makeLenses implementation. If you were previously using makeFieldsWith in order to provide a custom rule set, you should migrate to using makeLensesWith

  • Note: makeIsos was removed in the 4.3 release. Both makeLenses and makePrisms will generate an Iso when possible.

Data.Aeson.Lens split

The Data.Aeson.Lens module has been migrated back into its own package. This change will enable this module to continue to evolve its API beyond what we usually provide in the lens package and it reduces our direct package dependencies by three (aeson, scientific, attoparsec). This will also help to reduce build times, which can be particularly important to sandbox users.

http://hackage.haskell.org/package/lens-aeson

Miscellaneous

  • Review is now a proper supertype of Prism
  • makeLenses unifies field types for lenses/traversals spanning different field types.
  • GHC.Generics.Lens.tinplate works correctly on data types with both a single constructor and single field as well as empty data types.

Report your issues

Please report your issues to the GitHub issue tracker. While we'll be reading comments on Reddit, it will help to ensure our issue isn't lost.

https://github.com/ekmett/lens/issues

Posted Aug 22, 2014, 6:41 AM UTC

5118
ocharles•

Nice work guys! Especially happy to hear about makeClassyPrisms - I wrote those classes out by hand only a few weeks ago, and here you are already automating that work out of my hands. Can't complain :)

14
thang1thang2•

I was reading through the README and I had a question. Do all of the infix operators have verbal synonyms that can be used in the code? What I mean is, (.~) is an infix alias for `set', so you can use either/or.

On the other hand, +~ and *~, along with others, are also mentioned in the README, but I couldn't find a way to use them without using the infix operator as they don't seem to have names? Do they actually have names that you can use verbally and in the program? If not, are you planning on adding names to all of the infix operators?

Also, apologies if this isn't the right place, but holy shit some of these operators are just insane. <%@~, %%@=, <.&.~, do these actually have mnemonics or some other scheme in how they're composed so you can remember them? Or do you just have to wire it into your brain? (I would assume they have some mathematical logic notation background considering this is Haskell we're talking about...?)

9
Faucelme•

do these actually have mnemonics or some other scheme

For the setters, I think it is something like:

If it ends with ~ it is "pure", doesn't require a monadic context.

If it ends with = it works in MonadState.

If it begins with < it returns the result when applied (exceptions: operations that already have this character like the <> in <>~).

Also the presence of a @ seems to imply that the operator works with "indexed" lenses.

https://github.com/ekmett/lens/wiki/Operators

7
rwbarton•

They don't all have prefix-style names but consider that the underlying operators like + or .&. don't have prefix-style names either. l +~ n is over l (+ n), l *~ n is over l (* n), etc. Why invent a totally new name for the concept of +? Is it plusLens or addLens or additionLens or sumLens or incrementLens? Now do the same for - * / ^ ^^ ** || && <> .|. .&. </> <.>.

6
thang1thang2•

"Add together the numbers one and two...", or "Add one to two", or "the sum of one and two", etc. are the prefix verbal of +, and "the numbers one and two, the sum of which is...", "one and two, summed together, equal...", are postfix. Even though addition is "considered" infix, you can write it verbally all three ways.

I see your point, but it's unfortunate that the liberal usage of infix operators can make the code much harder to read and understand. The nature of haskell tends itself towards a prefix style of function declaration, and suddenly going from a prefix dominant coding style to one littered with infixes that you can't even name, but must simply attach to an abstract idea in your mind, is more than a little difficult at times.

As for names, why not pull them from wiki/Operators?

+~ addTo,  *~ multiplyTo, -~ subtractFrom, **~ raisePower, 
<>~ mappendTo, .|. bitwiseOrOf, </>~ appendPath

Of course I'm not nearly as versed in Lens (or Haskell, really) compared to you and everyone else using lens, but surely even some discussion or attempt at implementing names for the infix operators would be a good thing, right?

3
edwardkmett•

Based on my conversations with users of lens, I'd say the majority of the same people who don't like the operators at all are the same people who want a smaller core.

They usually prefer to just work with over as a single primitive to having dozens of names, regardless of whether those names happen to be prefix or not. They'd rather have one thing to learn that does them all.

You can always write the code you could with the operators without the operators, but it may be considerably more verbose.

7
rwbarton•

The point is

  1. once you know +~, then you also know *~, etc.
  2. once you know over l (+ n), then you also know over l (* n), etc.
  3. once you know addTo, you still have to learn multiplyTo and 12 more names.

If we already had standardized prefix names for +, * etc. that everyone knew, then we could choose systematic names for +~, *~ etc. and there would be just one thing to learn again. But we don't. Given that, I think that most people who don't like "option 1" above would prefer "option 2" to "option 3".

5
cdxr•

The nature of haskell tends itself towards a prefix style of function declaration, and suddenly going from a prefix dominant coding style to one littered with infixes that you can't even name, but must simply attach to an abstract idea in your mind, is more than a little difficult at times.

This is a matter of taste. I find the infix operators much easier to understand. When I see an operator like + or <> as the prefix of a larger operator, my mind immediately recognizes what is happening. It doesn't bother me that I don't have a name for it because I'm not thinking in terms of English. I wonder how most other people read it.

3
taylorfausak•

They don't all have names. The operators page on the wiki is the best resource I know of.

2
tdox•

Is the fourth column supposed to be "Stateful w/ Result" instead of just "w/ Result". (The second column is also "w/ Result".)

1
kqr•

Yes. I think you're meant to read the columns as compounding each other in pairs, so it's

  1. Combinators
  2. Combinators w/ result
  3. Stateful combinators
  4. Stateful combinators w/ result
1
tomejaguar•

Review is now a proper supertype of Prism

I don't get how this works. Choice was already a subclass of Profunctor so how did changing from Profunctor to Choice in the definition of Review make it a proper subtype supertype?

2
glguyOP•

A Prism is an optic that works for only the Choice profunctors, but a Review claimed to work for any Profunctor and therefore types that the Prism couldn't support. You have to keep in mind that these constraints are in a negative position so you have to flip your notion of containment around.

2
tomejaguar•

Ah yes, that negative position thing always confuses me. If you want to use a Prism somewhere a Review is expected then the constraints on Prism need to be weaker than the constraints on Review.

1
Peaker•

makeIsos was a particular pain point for me.

They also were reversed, compared with ordinary newtype field lenses!

1
glguyOP•

I hope it wasn't too much trouble. Here is the back story if you're interested.

https://github.com/ekmett/lens/issues/449

2
semigroup•

Exciting!

I've encountered what appears to be a breaking change though:

The following code previously didn't generate a lens for fromTimer, but now it does (well, attempts to do so) – I'm not sure if this is intentional: https://gist.github.com/iand675/ae489ed97cba90ade42b

1
glguyOP•

This was an unintentional discrepancy. I'll put out a fix. In the meantime your code should work with makeLensesWith camelCaseFields.

1