• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

benchmarks/H09-Sep-2001-472367

examples/H09-Sep-2001-489317

images/H03-May-2022-

include/H09-Sep-2001-5138

lens-properties/H09-Sep-2001-218140

src/H03-May-2022-31,09312,294

tests/H09-Sep-2001-1,056705

.gitignoreH A D09-Sep-2001192 2221

.hlint.yamlH A D09-Sep-20011.1 KiB2219

.vim.customH A D09-Sep-2001780 3223

AUTHORS.markdownH A D09-Sep-20013.3 KiB5041

CHANGELOG.markdownH A D09-Sep-200156 KiB1,088944

LICENSEH A D09-Sep-20011.2 KiB2721

README.markdownH A D09-Sep-20017.5 KiB242166

SUPPORT.markdownH A D09-Sep-2001712 117

Setup.lhsH A D09-Sep-2001123 76

cabal.projectH A D09-Sep-2001122 86

lens.cabalH A D03-May-202215.2 KiB505463

README.markdown

1Lens: Lenses, Folds, and Traversals
2==================================
3
4[![Hackage](https://img.shields.io/hackage/v/lens.svg)](https://hackage.haskell.org/package/lens) [![Build Status](https://github.com/ekmett/lens/workflows/Haskell-CI/badge.svg)](https://github.com/ekmett/lens/actions?query=workflow%3AHaskell-CI) [![Hackage Deps](https://img.shields.io/hackage-deps/v/lens.svg)](http://packdeps.haskellers.com/reverse/lens)
5
6This package provides families of [lenses](https://github.com/ekmett/lens/blob/master/src/Control/Lens/Type.hs), [isomorphisms](https://github.com/ekmett/lens/blob/master/src/Control/Lens/Iso.hs), [folds](https://github.com/ekmett/lens/blob/master/src/Control/Lens/Fold.hs), [traversals](https://github.com/ekmett/lens/blob/master/src/Control/Lens/Traversal.hs), [getters](https://github.com/ekmett/lens/blob/master/src/Control/Lens/Getter.hs) and [setters](https://github.com/ekmett/lens/blob/master/src/Control/Lens/Setter.hs).
7
8If you are looking for where to get started, [a crash course video](http://youtu.be/cefnmjtAolY?hd=1) 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](http://comonad.com/haskell/Lenses-Folds-and-Traversals-NYC.pdf) are also available if you want to use them to follow along.
9
10The [FAQ](https://github.com/ekmett/lens/wiki/FAQ), which provides links to a large number of different resources for learning about lenses and an overview of the [derivation](https://github.com/ekmett/lens/wiki/Derivation) of these types can be found on the [Lens Wiki](https://github.com/ekmett/lens/wiki) along with a brief [overview](https://github.com/ekmett/lens/wiki/Overview) and some [examples](https://github.com/ekmett/lens/wiki/Examples).
11
12Documentation is available through [github](http://ekmett.github.com/lens/frames.html) (for HEAD) or [hackage](http://hackage.haskell.org/package/lens) for the current and preceding releases.
13
14Field Guide
15-----------
16
17[![Lens Hierarchy](https://raw.githubusercontent.com/wiki/ekmett/lens/images/Hierarchy.png)](https://creately.com/diagram/h5nyo9ne1/QZ9UBOtw4AJWtmAKYK3wT8Mm1HM%3D)
18
19
20Examples
21--------
22
23(See [`wiki/Examples`](https://github.com/ekmett/lens/wiki/Examples))
24
25First, import `Control.Lens`.
26
27```haskell
28ghci> import Control.Lens
29```
30
31Now, you can read from lenses
32
33```haskell
34ghci> ("hello","world")^._2
35"world"
36```
37
38and you can write to lenses.
39
40```haskell
41ghci> set _2 42 ("hello","world")
42("hello",42)
43```
44
45Composing lenses for reading (or writing) goes in the order an imperative programmer would expect, and just uses `(.)` from the `Prelude`.
46
47```haskell
48ghci> ("hello",("world","!!!"))^._2._1
49"world"
50```
51
52```haskell
53ghci> set (_2._1) 42 ("hello",("world","!!!"))
54("hello",(42,"!!!"))
55```
56
57You can make a `Getter` out of a pure function with `to`.
58
59```haskell
60ghci> "hello"^.to length
615
62```
63
64You can easily compose a `Getter` with a `Lens` just using `(.)`. No explicit coercion is necessary.
65
66```haskell
67ghci> ("hello",("world","!!!"))^._2._2.to length
683
69```
70
71As we saw above, you can write to lenses and these writes can change the type of the container. `(.~)` is an infix alias for `set`.
72
73```haskell
74ghci> _1 .~ "hello" $ ((),"world")
75("hello","world")
76```
77
78Conversely `view`, can be used as a prefix alias for `(^.)`.
79
80```haskell
81ghci> view _2 (10,20)
8220
83```
84
85There are a large number of other lens variants provided by the library, in particular a `Traversal` generalizes `traverse` from `Data.Traversable`.
86
87We'll come back to those later, but continuing with just lenses:
88
89You can let the library automatically derive lenses for fields of your data type
90
91```haskell
92data Foo a = Foo { _bar :: Int, _baz :: Int, _quux :: a }
93makeLenses ''Foo
94```
95
96This will automatically generate the following lenses:
97
98```haskell
99bar, baz :: Lens' (Foo a) Int
100quux :: Lens (Foo a) (Foo b) a b
101```
102
103A `Lens` takes 4 parameters because it can change the types of the whole when you change the type of the part.
104
105Often you won't need this flexibility, a `Lens'` takes 2 parameters, and can be used directly as a `Lens`.
106
107You can also write to setters that target multiple parts of a structure, or their composition with other
108lenses or setters. The canonical example of a setter is 'mapped':
109
110```haskell
111mapped :: Functor f => Setter (f a) (f b) a b
112```
113
114`over` is then analogous to `fmap`, but parameterized on the Setter.
115
116```haskell
117ghci> fmap succ [1,2,3]
118[2,3,4]
119ghci> over mapped succ [1,2,3]
120[2,3,4]
121```
122
123The benefit is that you can use any `Lens` as a `Setter`, and the composition of setters with other setters or lenses using `(.)` yields
124a `Setter`.
125
126```haskell
127ghci> over (mapped._2) succ [(1,2),(3,4)]
128[(1,3),(3,5)]
129```
130
131`(%~)` is an infix alias for 'over', and the precedence lets you avoid swimming in parentheses:
132
133```haskell
134ghci> _1.mapped._2.mapped %~ succ $ ([(42, "hello")],"world")
135([(42, "ifmmp")],"world")
136```
137
138There are a number of combinators that resemble the `+=`, `*=`, etc. operators from C/C++ for working with the monad transformers.
139
140There are `+~`, `*~`, etc. analogues to those combinators that work functionally, returning the modified version of the structure.
141
142```haskell
143ghci> both *~ 2 $ (1,2)
144(2,4)
145```
146
147There are combinators for manipulating the current state in a state monad as well
148
149```haskell
150fresh :: MonadState Int m => m Int
151fresh = id <+= 1
152```
153
154Anything you know how to do with a `Foldable` container, you can do with a `Fold`
155
156```haskell
157ghci> :m + Data.Char Data.Text.Lens
158ghci> allOf (folded.text) isLower ["hello"^.packed, "goodbye"^.packed]
159True
160```
161
162You can also use this for generic programming. Combinators are included that are based on Neil Mitchell's `uniplate`, but which
163have been generalized to work on or as lenses, folds, and traversals.
164
165```haskell
166ghci> :m + Data.Data.Lens
167ghci> anyOf biplate (=="world") ("hello",(),[(2::Int,"world")])
168True
169```
170
171As alluded to above, anything you know how to do with a `Traversable` you can do with a `Traversal`.
172
173```haskell
174ghci> mapMOf (traverse._2) (\xs -> length xs <$ putStrLn xs) [(42,"hello"),(56,"world")]
175"hello"
176"world"
177[(42,5),(56,5)]
178```
179
180Moreover, many of the lenses supplied are actually isomorphisms, that means you can use them directly as a lens or getter:
181
182```haskell
183ghci> let hello = "hello"^.packed
184"hello"
185ghci> :t hello
186hello :: Text
187```
188
189but you can also flip them around and use them as a lens the other way with `from`!
190
191```haskell
192ghci> hello^.from packed.to length
1935
194```
195
196You can automatically derive isomorphisms for your own newtypes with `makePrisms`. e.g.
197
198```haskell
199newtype Neither a b = Neither { _nor :: Either a b } deriving (Show)
200makePrisms ''Neither
201```
202
203will automatically derive
204
205```haskell
206_Neither :: Iso (Neither a b) (Neither c d) (Either a b) (Either c d)
207```
208
209such that
210
211```haskell
212_Neither.from _Neither = id
213from _Neither._Neither = id
214```
215
216Alternatively, you can use `makeLenses` to automatically derive isomorphisms for your own newtypes. e.g..
217
218```hs
219makeLenses ''Neither
220```
221
222will automatically derive
223
224```hs
225nor :: Iso (Either a b) (Either c d) (Neither a b) (Neither c d)
226```
227
228which behaves identically to `_Neither` above.
229
230There is also a fully operational, but simple game of [Pong](https://github.com/ekmett/lens/blob/master/examples/Pong.hs) in the [examples/](https://github.com/ekmett/lens/blob/master/examples/) folder.
231
232There are also a couple of hundred examples distributed throughout the haddock documentation.
233
234Contact Information
235-------------------
236
237Contributions and bug reports are welcome!
238
239Please feel free to contact me through github or on the #haskell IRC channel on irc.freenode.net.
240
241-Edward Kmett
242