• Stars
    star
    1,992
  • Rank 22,448 (Top 0.5 %)
  • Language
    Haskell
  • License
    Other
  • Created almost 12 years ago
  • Updated 17 days ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Lenses, Folds, and Traversals - Join us on web.libera.chat #haskell-lens

Lens: Lenses, Folds, and Traversals

Hackage Build Status Hackage Deps

This package provides families of lenses, isomorphisms, folds, traversals, getters and setters.

If you are looking for where to get started, a crash course video on how lens was constructed and how to use the basics is available on youtube. It is best watched in high definition to see the slides, but the slides are also available if you want to use them to follow along.

The FAQ, which provides links to a large number of different resources for learning about lenses and an overview of the derivation of these types can be found on the Lens Wiki along with a brief overview and some examples.

Documentation is available through github (for HEAD) or hackage for the current and preceding releases.

Field Guide

Lens Hierarchy

Examples

(See wiki/Examples)

First, import Control.Lens.

ghci> import Control.Lens

Now, you can read from lenses

ghci> ("hello","world")^._2
"world"

and you can write to lenses.

ghci> set _2 42 ("hello","world")
("hello",42)

Composing lenses for reading (or writing) goes in the order an imperative programmer would expect, and just uses (.) from the Prelude.

ghci> ("hello",("world","!!!"))^._2._1
"world"
ghci> set (_2._1) 42 ("hello",("world","!!!"))
("hello",(42,"!!!"))

You can make a Getter out of a pure function with to.

ghci> "hello"^.to length
5

You can easily compose a Getter with a Lens just using (.). No explicit coercion is necessary.

ghci> ("hello",("world","!!!"))^._2._2.to length
3

As we saw above, you can write to lenses and these writes can change the type of the container. (.~) is an infix alias for set.

ghci> _1 .~ "hello" $ ((),"world")
("hello","world")

Conversely view, can be used as a prefix alias for (^.).

ghci> view _2 (10,20)
20

There are a large number of other lens variants provided by the library, in particular a Traversal generalizes traverse from Data.Traversable.

We'll come back to those later, but continuing with just lenses:

You can let the library automatically derive lenses for fields of your data type

data Foo a = Foo { _bar :: Int, _baz :: Int, _quux :: a }
makeLenses ''Foo

This will automatically generate the following lenses:

bar, baz :: Lens' (Foo a) Int
quux :: Lens (Foo a) (Foo b) a b

A Lens takes 4 parameters because it can change the types of the whole when you change the type of the part.

Often you won't need this flexibility, a Lens' takes 2 parameters, and can be used directly as a Lens.

You can also write to setters that target multiple parts of a structure, or their composition with other lenses or setters. The canonical example of a setter is 'mapped':

mapped :: Functor f => Setter (f a) (f b) a b

over is then analogous to fmap, but parameterized on the Setter.

ghci> fmap succ [1,2,3]
[2,3,4]
ghci> over mapped succ [1,2,3]
[2,3,4]

The benefit is that you can use any Lens as a Setter, and the composition of setters with other setters or lenses using (.) yields a Setter.

ghci> over (mapped._2) succ [(1,2),(3,4)]
[(1,3),(3,5)]

(%~) is an infix alias for 'over', and the precedence lets you avoid swimming in parentheses:

ghci> _1.mapped._2.mapped %~ succ $ ([(42, "hello")],"world")
([(42, "ifmmp")],"world")

There are a number of combinators that resemble the +=, *=, etc. operators from C/C++ for working with the monad transformers.

There are +~, *~, etc. analogues to those combinators that work functionally, returning the modified version of the structure.

ghci> both *~ 2 $ (1,2)
(2,4)

There are combinators for manipulating the current state in a state monad as well

fresh :: MonadState Int m => m Int
fresh = id <+= 1

Anything you know how to do with a Foldable container, you can do with a Fold

ghci> :m + Data.Char Data.Text.Lens
ghci> allOf (folded.text) isLower ["hello"^.packed, "goodbye"^.packed]
True

You can also use this for generic programming. Combinators are included that are based on Neil Mitchell's uniplate, but which have been generalized to work on or as lenses, folds, and traversals.

ghci> :m + Data.Data.Lens
ghci> anyOf biplate (=="world") ("hello",(),[(2::Int,"world")])
True

As alluded to above, anything you know how to do with a Traversable you can do with a Traversal.

ghci> mapMOf (traverse._2) (\xs -> length xs <$ putStrLn xs) [(42,"hello"),(56,"world")]
"hello"
"world"
[(42,5),(56,5)]

Moreover, many of the lenses supplied are actually isomorphisms, that means you can use them directly as a lens or getter:

ghci> let hello = "hello"^.packed
"hello"
ghci> :t hello
hello :: Text

but you can also flip them around and use them as a lens the other way with from!

ghci> hello^.from packed.to length
5

You can automatically derive isomorphisms for your own newtypes with makePrisms. e.g.

newtype Neither a b = Neither { _nor :: Either a b } deriving (Show)
makePrisms ''Neither

will automatically derive

_Neither :: Iso (Neither a b) (Neither c d) (Either a b) (Either c d)

such that

_Neither.from _Neither = id
from _Neither._Neither = id

Alternatively, you can use makeLenses to automatically derive isomorphisms for your own newtypes. e.g..

makeLenses ''Neither

will automatically derive

nor :: Iso (Either a b) (Either c d) (Neither a b) (Neither c d)

which behaves identically to _Neither above.

There is also a fully operational, but simple game of Pong in the examples/ folder.

There are also a couple of hundred examples distributed throughout the haddock documentation.

Contact Information

Contributions and bug reports are welcome!

Please feel free to contact me through GitHub or on the #haskell-lens or #haskell IRC channel on Libera Chat.

-Edward Kmett

More Repositories

1

ad

Automatic Differentiation
Haskell
364
star
2

machines

Networks of composable stream transducers
Haskell
338
star
3

trifecta

Parser combinators with highlighting, slicing, layout, literate comments, Clang-style diagnostics and the kitchen sink
Haskell
294
star
4

guanxi

Relational programming in Haskell. Mostly developed on twitch.
Haskell
250
star
5

quine

haskell, opengl, toy project
Haskell
211
star
6

linear

Low-dimensional linear algebra primitives for Haskell.
Haskell
195
star
7

hask

Category theory for Haskell with a lens flavor (you need GHC 7.8.3, not 7.8.2 to build this!)
Haskell
161
star
8

propagators

The Art of the Propagator. See also:
Haskell
160
star
9

coda

A language experiment -- irc.freenode.net ##coda
Haskell
159
star
10

free

free monads
Haskell
157
star
11

discrimination

Fast linear time sorting and discrimination for a large class of data types
Haskell
135
star
12

bound

Combinators for manipulating locally-nameless generalized de Bruijn terms
Haskell
121
star
13

reflection

Reifies arbitrary Haskell terms into types that can be reflected back into terms
Haskell
101
star
14

algebra

constructive abstract algebra
Haskell
98
star
15

succinct

playground for working with succinct data structures
Haskell
93
star
16

gl

Complete raw OpenGL bindings for Haskell
Haskell
92
star
17

parsers

Generic parser combinators
Haskell
88
star
18

linear-logic

Haskell
81
star
19

tables

Deprecated because of
Haskell
78
star
20

comonad

Haskell 98 comonads
Haskell
77
star
21

semigroupoids

Haskell
75
star
22

kan-extensions

Kan extensions, Kan lifts, the Yoneda lemma, and (co)monads generated by a functor
Haskell
74
star
23

contravariant

Haskell 98 contravariant functors
Haskell
72
star
24

constraints

Tools for programming with ConstraintKinds in GHC
Haskell
70
star
25

profunctors

Haskell 98 Profunctors
Haskell
69
star
26

cadenza

every day i'm truffling
Kotlin
67
star
27

codex

UI experiments for coda
Haskell
65
star
28

approximate

Approximate discrete values and numbers
Haskell
64
star
29

structures

A playground for working on advanced data structures in Haskell
Haskell
63
star
30

semigroups

Haskell 98 semigroups
Haskell
62
star
31

ersatz

A monad for interfacing with external SAT solvers
Haskell
62
star
32

bifunctors

Haskell 98 bifunctors, bifoldables and bitraversables
Haskell
56
star
33

either

the EitherT monad transformer
Haskell
54
star
34

unpacked-containers

Unpacked containers using backpack
Haskell
51
star
35

exceptions

mtl friendly exceptions
Haskell
48
star
36

structs

Exploring how to make a strict imperative universe in the GHC runtime system.
Haskell
47
star
37

reducers

Semigroups, specialized containers and a general map/reduce framework
Haskell
46
star
38

adjunctions

Simple adjunctions
Haskell
44
star
39

distributive

Dual Traversable
Haskell
41
star
40

auth

Haskell
39
star
41

graphs

a monadic graph library
Haskell
39
star
42

zippers

Zippers based on lenses and traversals
Haskell
38
star
43

tagged

phantom types
Haskell
37
star
44

unboxed

experimenting with unlifted classes via backpack
Haskell
36
star
45

categories

categories from category-extras
Haskell
34
star
46

perhaps

A monad, perhaps.
Haskell
33
star
47

rounded

MPFR bindings for Haskell
Haskell
33
star
48

transients

Clojure-style transients for Haskell
Haskell
32
star
49

hyphenation

Knuth-Liang Hyphenation for Haskell based on TeX hyphenation files
Haskell
32
star
50

concurrent

Yet another concurrent playground
Haskell
32
star
51

abelian

Commutative Applicatives and Semigroups
Haskell
31
star
52

hkd

higher-kinded data
Haskell
29
star
53

speculation

Safe, programmable, speculative evaluation for Haskell
Haskell
29
star
54

rts

spmd-on-simd stuff
C++
28
star
55

promises

lazy promises
Haskell
27
star
56

intervals

Interval Arithmetic
Haskell
27
star
57

heaps

Asymptotically optimal Brodal/Okasaki heaps
Haskell
26
star
58

intern

Hash consing for arbitrary Haskell data types
Haskell
25
star
59

hyperloglog

A constant-memory approximation of set membership
Haskell
24
star
60

magpie

an exploration of subtyping-based category theory in scala
Scala
24
star
61

lca

Improves the known complexity of online lowest common ancestor search to O(log h) persistently, and without preprocessing
Haskell
24
star
62

sparse

sparse matrices in Morton order
Haskell
23
star
63

streams

Haskell 2010 stream comonads
Haskell
22
star
64

keys

keyed functors
Haskell
22
star
65

bytes

Serialization primitives that work with both cereal and binary.
Haskell
22
star
66

pointed

pointed and copointed data
Haskell
21
star
67

scala-ad

Forward- and Reverse-Mode Automatic Differentiation for Scala
Scala
21
star
68

vr

nothing to see here
C++
20
star
69

name

nominal sets in haskell
Haskell
20
star
70

indexed

Indexed Functors for GHC 7.6
Haskell
19
star
71

fractions

lazy continued fractions
Haskell
19
star
72

rope

Fingertrees of Bytestrings
Haskell
19
star
73

jitplusplus

a tracing jit for c++ based on tracing and compiling from x86-64 assembly to x86-64 assembly
C
19
star
74

void

Provides Data.Void, which is in base since ghc 7.8 or so
Haskell
19
star
75

scheme-monads

minimalist polymorphic scheme-(co)monads, written to avoid use of any advanced language features except hygienic macros
Scheme
18
star
76

folds

Folds and sequence algebras
Haskell
18
star
77

parsnip

Haskell
18
star
78

category-extras

category-theoretic goodness for Haskell
Haskell
17
star
79

concurrent-supply

A fast globally unique variable supply with a pure API
Haskell
17
star
80

homotopy

Coq
17
star
81

thc

An experimental "Turbo" Haskell Runtime - Nothing really to see here yet
C++
17
star
82

lens-action

Control.Lens.Action
Haskell
17
star
83

rcu

experimenting with STM-backed read-copy-update in Haskell
Haskell
16
star
84

multicategories

Playing around with multicategories and operads
Haskell
16
star
85

bad

a playground for working with fully static tensors and automatic differentiation
C++
16
star
86

gc

Poor Richard's Memory Manager
Haskell
15
star
87

scala-attoparsec

A port of Bryan O'Sullivan's attoparsec from Haskell to Scala
Scala
15
star
88

kanso

just a place to throw some coding experiements while i re-re-re-learn rust
Rust
15
star
89

hyperfunctions

playing with hyperfunctions
Haskell
15
star
90

succinct-binary

Succinct binary serialization
Haskell
15
star
91

half

half-precision floating-point
Haskell
14
star
92

time-series

Playing with time series
Haskell
14
star
93

codebruijn

experiments with pext/pdep and codebruijn syntax
Haskell
14
star
94

haskell

An unimaginatively named monorepo for misc. side-projects that are annoying to maintain separately.
Haskell
14
star
95

compensated

Compensated floating-point arithmetic
Haskell
13
star
96

eq

Leibnizian type equality
Haskell
13
star
97

nbe-in-java-19

a throwaway implementation of normalization by evaluation
Java
13
star
98

bits

Bit twiddling and bitwise serialization primitives
Haskell
13
star
99

hybrid-vectors

Hybrid vectors e.g. mixed boxed/unboxed vectors that are suitable for use with vector-algorithms
Haskell
13
star
100

monad-ran

Right Kan extension transformers covering the entire MTL, IO, ST s, and STM in Haskell in a generalization of continuation passing style
Haskell
13
star