LensesMiscellaneous
Lenses are a universal solution to data manipulation in Haskell. They make working with nested data (tuples, records, lists of vectors of tuples of records) easy.
You can use fst
to get the first element of a pair, and you can write \(_, b) -> (a, b)
to change the first element of a pair – wouldn't it be nice if you could do both with the same function? Well, lenses do exactly that. Additionally, you can combine lenses into chains – for instance, if you want to modify the n-th element of a list buried inside a tuple that is a record field, with lens you can do it as set (someField . _1 . ix n) someValue
. Look at this post to see the power of lenses for yourself.
All libraries here provide a way to automatically generate lenses for a record (since it's one of the most common uses for lenses). Some also provide stock lenses for common types like tuples, lists, Either
, and more.
“van Laarhoven” refers to a particular type of lenses that can be defined without depending on any lens library and are generally very clever and very generalisable (but they can be somewhat hard to understand).
Recommendations
-
If you don't mind dependencies, just use lens. It's the most used package and the most featureful one.
-
If you mind dependencies, use microlens, which lets you choose exactly what dependencies you want/don't want and follows lens closely.
-
If you're only starting with lenses, probably use microlens/microlens-platform as it's got nice docs and lots of examples, but be prepared to look into lens-simple's source.
-
Rather small, has few dependencies.
-
Unlike microlens, has
*Of
functions and many operators from lens (<>~
,&&=
, etc). -
The implementation is simpler than that of either lens or microlens (so it could be good for studying how lenses work).
-
Doesn't use overloading, so
_1
and_2
only work on pairs,ix
doesn't work with lists, andat
only works withMap
. If you try to use it for a big project, you might end up annoyed with missing functionality. -
Doesn't provide lens's more advanced features (like prisms or indexed traversals).
-
Its
Fold
can't be used by functions from lens that take aFold
from lens, which potentially hurts compatibility a bit. -
Could be slower than lens (due to the absence of
INLINE
pragmas – but I haven't benchmarked).
A fork of lens that explicitly tries to be as small as possible while still being useful (e.g. all extra features are split into separate packages). Provides a somewhat different set of functions than lens-simple, but generally is closer to lens than lens-simple is. Like lens, uses ad-hoc typeclasses to provide overloaded lenses.
-
Very small (the base package has no dependencies at all).
-
Has better documentation than either lens-simple or lens.
-
It's just a fork of lens, so nothing has been renamed and everything behaves in the same way. (And also it should be just as fast.)
-
Doesn't omit overloaded lenses (so
at
and_1
work with many things) – and it also provideseach
, a traversal that can traverse mostly everything.
-
Doesn't provide lens's more advanced features (like prisms or indexed traversals).
-
Doesn't let you write code in fully “lensy” style (since it omits lots of operators and
*Of
functions from lens). -
Provides orphan instances in microlens-ghc and microlens-platform.
Official:
- microlens-th for automatic lens generation
- microlens-mtl with mtl-related things like
zoom
and.=
- microlens-ghc (instances for libraries shipped with GHC)
- microlens-platform (instances for vector, text, etc)
- microlens-contra – true
Getter
andFold
Unofficial:
- microlens-aeson – lenses for aeson
- zlib-lens – not made for microlens but can be used with it
-
The most popular lens library, by a huge margin (and one of most popular overall on Hackage).
-
Contains pretty much everything you could want – in addition to usual lenses (for manipulating lists, maps, tuples, and standard types like
Maybe
/Either
/etc), lens has functions for manipulating filepaths, Template Haskell structures, generics, complex numbers, exceptions,Text
,Vector
,ByteString
, and so on. Other libraries aren't even close. -
Unlike most other libraries, has prisms – a kind of lenses that can act both as constructors and deconstructors at once. They can be pretty useful when you're dealing with exceptions, Template Haskell, JSON, sum types, etc.
-
Probably the most performant one.
-
Takes a lot of time to compile, and has a lot of dependencies as well.
-
Some of its advanced features are very intimidating, and the whole library may seem overengineered. See this post.
-
Once you start using lenses for everything (which happens often to users of lens), your code may start not looking like Haskell much and people not used to this style will have a hard time understanding it. See this post.
-
Doesn't have (unlawful) monadic lenses (i.e. you can't write something like
Lens' (IORef a) a
).
-
Lenses for types provided in various libraries: lens-aeson, lens-datetime, xml-lens, pandoc-lens, cabal-lenses, wai-lens, twitter-types-lens, simpleirc-lens
-
Testing your lenses: smallcheck-lens (for smallcheck), lens-properties (for quickcheck), tasty-lens (for tasty)
-
Lenses as interfaces for other libraries: zlib-lens (compress things using lenses), lens-regex (use regexes with lenses)
-
Various: lens-tutorial (a tutorial package), lens-action (monadic getters), total (a library for total pattern matching with lenses – see this post)
-
Few dependencies (compared to lens).
-
Has lenses that can report errors (via
Either
). -
Has monadic lenses (e.g. you could make a lens that reads a file, or an
IORef
, or something from a database). -
Lets you compose lenses into bigger lenses (a pretty unique feature among lens libraries – all other libraries require you to write lenses manually or provide a getter and a setter).
-
Can make lenses for GADTs (see an example in the notes).
-
Doesn't have traversals at all. (Apart from “partial lenses” like
just
.) -
Provides very few lenses.
-
Is designed to be imported qualified (which can be annoying), and you have to
import Prelude hiding (id, (.))
as well if you want to use it.