Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 460 lines (410 sloc) 17.273 kB
6be7786 @ekmett Factoring out Control.Lens.Type
authored
1 {-# LANGUAGE CPP #-}
2 {-# LANGUAGE GADTs #-}
3 {-# LANGUAGE Rank2Types #-}
4 {-# LANGUAGE FlexibleContexts #-}
5 {-# LANGUAGE FlexibleInstances #-}
6 {-# LANGUAGE ScopedTypeVariables #-}
7 {-# LANGUAGE MultiParamTypeClasses #-}
8 -------------------------------------------------------------------------------
9 -- |
10 -- Module : Control.Lens.Type
11 -- Copyright : (C) 2012 Edward Kmett
12 -- License : BSD-style (see the file LICENSE)
13 -- Maintainer : Edward Kmett <ekmett@gmail.com>
14 -- Stability : provisional
15 -- Portability : Rank2Types
16 --
17 -------------------------------------------------------------------------------
18 module Control.Lens.Type
19 (
20 -- * Lenses, Folds and Traversals
21 Lens, Lens'
22 , Traversal, Traversal'
23 , Iso, Iso'
24 , Prism , Prism'
25 , Setter, Setter'
3ce55f4 @ekmett Added 'Control.Lens.Equality'
authored
26 , Equality, Equality'
6be7786 @ekmett Factoring out Control.Lens.Type
authored
27 , Getter
28 , Fold
29 , Action
30 , MonadicFold
31 -- * Indexed Variants
32 , IndexedLens, IndexedLens'
33 , IndexedTraversal, IndexedTraversal'
34 , IndexedSetter, IndexedSetter'
35 , IndexedGetter
36 , IndexedFold
37 , IndexedAction
38 , IndexedMonadicFold
39 -- * Common
40 , Simple
41 , LensLike, LensLike'
42 , IndexedLensLike, IndexedLensLike'
43 , Overloading, Overloading'
44 ) where
45
46 import Control.Applicative
47 import Control.Lens.Internal
48 import Data.Profunctor
49
50 -- $setup
51 -- >>> import Control.Lens
52 -- >>> import Debug.SimpleReflect.Expr
53 -- >>> import Debug.SimpleReflect.Vars as Vars hiding (f,g,h)
54 -- >>> let f :: Expr -> Expr; f = Debug.SimpleReflect.Vars.f
55 -- >>> let g :: Expr -> Expr; g = Debug.SimpleReflect.Vars.g
56 -- >>> let h :: Expr -> Expr -> Expr; h = Debug.SimpleReflect.Vars.h
57 -- >>> let getter :: Expr -> Expr; getter = fun "getter"
58 -- >>> let setter :: Expr -> Expr -> Expr; setter = fun "setter"
5095463 @ekmett fixed prism test
authored
59 -- >>> import Numeric.Natural
e95b155 @ion1 Prism, Type: Apply the previous fix to the right place; remove $setup…
ion1 authored
60 -- >>> let nat :: Prism' Integer Natural; nat = prism toInteger $ \i -> if i < 0 then Left i else Right (fromInteger i)
6be7786 @ekmett Factoring out Control.Lens.Type
authored
61
62 -------------------------------------------------------------------------------
63 -- Lenses
64 -------------------------------------------------------------------------------
65
66 -- | A 'Lens' is actually a lens family as described in
67 -- <http://comonad.com/reader/2012/mirrored-lenses/>.
68 --
69 -- With great power comes great responsibility and a 'Lens' is subject to the
70 -- three common sense lens laws:
71 --
72 -- 1) You get back what you put in:
73 --
74 -- @'Control.Lens.Getter.view' l ('Control.Lens.Setter.set' l b a) ≡ b@
75 --
76 -- 2) Putting back what you got doesn't change anything:
77 --
78 -- @'Control.Lens.Setter.set' l ('Control.Lens.Getter.view' l a) a ≡ a@
79 --
80 -- 3) Setting twice is the same as setting once:
81 --
82 -- @'Control.Lens.Setter.set' l c ('Control.Lens.Setter.set' l b a) ≡ 'Control.Lens.Setter.set' l c a@
83 --
84 -- These laws are strong enough that the 4 type parameters of a 'Lens' cannot
85 -- vary fully independently. For more on how they interact, read the \"Why is
86 -- it a Lens Family?\" section of
87 -- <http://comonad.com/reader/2012/mirrored-lenses/>.
88 --
89 -- Every 'Lens' can be used directly as a 'Control.Lens.Setter.Setter' or
90 -- 'Traversal'.
91 --
92 -- You can also use a 'Lens' for 'Control.Lens.Getter.Getting' as if it were a
93 -- 'Fold' or 'Getter'.
94 --
95 -- Since every lens is a valid 'Traversal', the
96 -- traversal laws are required of any lenses you create:
97 --
98 -- @
99 -- l 'pure' ≡ 'pure'
100 -- 'fmap' (l f) '.' l g ≡ 'Data.Functor.Compose.getCompose' '.' l ('Data.Functor.Compose.Compose' '.' 'fmap' f '.' g)
101 -- @
102 --
103 -- @type 'Lens' s t a b = forall f. 'Functor' f => 'LensLike' f s t a b@
104 type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t
105
106 -- | @type 'Lens'' = 'Simple' 'Lens'@
107 type Lens' s a = Lens s s a a
108
109 ------------------------------------------------------------------------------
110 -- Indexed Lenses
111 ------------------------------------------------------------------------------
112
113 -- | Every 'IndexedLens' is a valid 'Lens' and a valid 'Control.Lens.Traversal.IndexedTraversal'.
114 type IndexedLens i s t a b = forall f p. (Indexable i p, Functor f) => p a (f b) -> s -> f t
115
116 -- | @type 'IndexedLens'' i = 'Simple' ('IndexedLens' i)@
117 type IndexedLens' i s a = IndexedLens i s s a a
118
119 ------------------------------------------------------------------------------
120 -- Traversals
121 ------------------------------------------------------------------------------
122
123 -- | A 'Traversal' can be used directly as a 'Control.Lens.Setter.Setter' or a 'Fold' (but not as a 'Lens') and provides
124 -- the ability to both read and update multiple fields, subject to some relatively weak 'Traversal' laws.
125 --
126 -- These have also been known as multilenses, but they have the signature and spirit of
127 --
128 -- @'traverse' :: 'Traversable' f => 'Traversal' (f a) (f b) a b@
129 --
130 -- and the more evocative name suggests their application.
131 --
132 -- Most of the time the 'Traversal' you will want to use is just 'traverse', but you can also pass any
133 -- 'Lens' or 'Iso' as a 'Traversal', and composition of a 'Traversal' (or 'Lens' or 'Iso') with a 'Traversal' (or 'Lens' or 'Iso')
134 -- using (.) forms a valid 'Traversal'.
135 --
136 -- The laws for a Traversal @t@ follow from the laws for Traversable as stated in \"The Essence of the Iterator Pattern\".
137 --
138 -- @
139 -- t 'pure' ≡ 'pure'
140 -- 'fmap' (t f) '.' t g ≡ 'Data.Functor.Compose.getCompose' '.' t ('Data.Functor.Compose.Compose' '.' 'fmap' f '.' g)
141 -- @
142 --
143 -- One consequence of this requirement is that a 'Traversal' needs to leave the same number of elements as a
144 -- candidate for subsequent 'Traversal' that it started with. Another testament to the strength of these laws
145 -- is that the caveat expressed in section 5.5 of the \"Essence of the Iterator Pattern\" about exotic
146 -- 'Traversable' instances that 'traverse' the same entry multiple times was actually already ruled out by the
147 -- second law in that same paper!
148 type Traversal s t a b = forall f. Applicative f => (a -> f b) -> s -> f t
149
150 -- | @type 'Traversal'' = 'Simple' 'Traversal'@
151 type Traversal' s a = Traversal s s a a
152
153 ------------------------------------------------------------------------------
154 -- Indexed Traversals
155 ------------------------------------------------------------------------------
156
157 -- | Every indexed traversal is a valid 'Control.Lens.Traversal.Traversal' or
158 -- 'Control.Lens.Fold.IndexedFold'.
159 --
160 -- The 'Indexed' constraint is used to allow an 'IndexedTraversal' to be used
161 -- directly as a 'Control.Lens.Traversal.Traversal'.
162 --
163 -- The 'Control.Lens.Traversal.Traversal' laws are still required to hold.
164 type IndexedTraversal i s t a b = forall f p. (Indexable i p, Applicative f) => p a (f b) -> s -> f t
165
166 -- | @type 'IndexedTraversal'' i = 'Simple' ('IndexedTraversal' i)@
167 type IndexedTraversal' i s a = IndexedTraversal i s s a a
168
169 ------------------------------------------------------------------------------
170 -- Setters
171 ------------------------------------------------------------------------------
172
173 -- |
174 -- The only 'Lens'-like law that can apply to a 'Setter' @l@ is that
175 --
176 -- @'set' l y ('set' l x a) ≡ 'set' l y a@
177 --
178 -- You can't 'view' a 'Setter' in general, so the other two laws are irrelevant.
179 --
180 -- However, two 'Functor' laws apply to a 'Setter':
181 --
182 -- @
183 -- 'over' l 'id' ≡ 'id'
184 -- 'over' l f '.' 'over' l g ≡ 'over' l (f '.' g)
185 -- @
186 --
187 -- These an be stated more directly:
188 --
189 -- @
190 -- l 'pure' ≡ 'pure'
191 -- l f . 'untainted' . l g ≡ l (f . 'untainted' . g)
192 -- @
193 --
194 -- You can compose a 'Setter' with a 'Lens' or a 'Traversal' using ('.') from the Prelude
195 -- and the result is always only a 'Setter' and nothing more.
196 --
197 -- >>> over traverse f [a,b,c,d]
198 -- [f a,f b,f c,f d]
199 --
200 -- >>> over _1 f (a,b)
201 -- (f a,b)
202 --
203 -- >>> over (traverse._1) f [(a,b),(c,d)]
204 -- [(f a,b),(f c,d)]
205 --
206 -- >>> over both f (a,b)
207 -- (f a,f b)
208 --
209 -- >>> over (traverse.both) f [(a,b),(c,d)]
210 -- [(f a,f b),(f c,f d)]
211 type Setter s t a b = forall f. Settable f => (a -> f b) -> s -> f t
212
213 -- |
214 --
215 -- A 'Setter'' is just a 'Setter' that doesn't change the types.
216 --
217 -- These are particularly common when talking about monomorphic containers. /e.g./
218 --
219 -- @'sets' Data.Text.map :: 'Setter'' 'Data.Text.Internal.Text' 'Char'@
220 --
221 -- @type 'Setter'' = 'Setter''@
222 type Setter' s a = Setter s s a a
223
224 -- | Every 'IndexedSetter' is a valid 'Setter'
225 --
226 -- The 'Setter' laws are still required to hold.
227 type IndexedSetter i s t a b = forall f p.
228 (Indexable i p, Settable f) => p a (f b) -> s -> f t
229
230 -- |
231 -- @type 'IndexedSetter'' i = 'Simple' ('IndexedSetter' i)@
232 type IndexedSetter' i s a = IndexedSetter i s s a a
233
234 -----------------------------------------------------------------------------
235 -- Isomorphisms
236 -----------------------------------------------------------------------------
237
238 -- | Isomorphism families can be composed with other lenses using ('.') and 'id'.
239 type Iso s t a b = forall p f. (Profunctor p, Functor f) => p a (f b) -> p s (f t)
240
241 -- |
242 -- @type 'Iso'' = 'Control.Lens.Type.Simple' 'Iso'@
243 type Iso' s a = Iso s s a a
244
245 ------------------------------------------------------------------------------
246 -- Prism Internals
247 ------------------------------------------------------------------------------
248
249 -- | A 'Prism' @l@ is a 0-or-1 target 'Traversal' that can also be turned around with 'remit' to
250 -- obtain a 'Getter' in the opposite direction.
251 --
252 -- There are two laws that a 'Prism' should satisfy:
253 --
254 -- First, if I 'remit' or 'Control.Lens.Prism.review' a value with a 'Prism' and then 'Control.Lens.Prism.preview' or use ('^?'), I will get it back:
255 --
256 -- * @'Control.Lens.Prism.preview' l ('Control.Lens.Prism.review' l b) ≡ 'Just' b@
257 --
258 -- Second, if you can extract a value @a@ using a Prism @l@ from a value @s@, then the value @s@ is completely described my @l@ and @a@:
259 --
260 -- * If @'Control.Lens.Prism.preview' l s ≡ 'Just' a@ then @'Control.Lens.Prism.review' l a ≡ s@
261 --
262 -- These two laws imply that the 'Traversal' laws hold for every 'Prism' and that we 'traverse' at most 1 element:
263 --
264 -- @'Control.Lens.Fold.lengthOf' l x '<=' 1@
265 --
266 -- It may help to think of this as a 'Iso' that can be partial in one direction.
267 --
268 -- Every 'Prism' is a valid 'Traversal'.
269 --
270 -- Every 'Iso' is a valid 'Prism'.
271 --
272 -- For example, you might have a @'Prism'' 'Integer' Natural@ allows you to always
273 -- go from a 'Natural' to an 'Integer', and provide you with tools to check if an 'Integer' is
274 -- a 'Natural' and/or to edit one if it is.
275 --
276 --
277 -- @
278 -- 'nat' :: 'Prism'' 'Integer' 'Numeric.Natural.Natural'
279 -- 'nat' = 'prism' 'toInteger' '$' \\ i ->
280 -- if i '<' 0
281 -- then 'Left' i
282 -- else 'Right' ('fromInteger' i)
283 -- @
284 --
285 -- Now we can ask if an 'Integer' is a 'Natural'.
286 --
287 -- >>> 5^?nat
288 -- Just 5
289 --
290 -- >>> (-5)^?nat
291 -- Nothing
292 --
293 -- We can update the ones that are:
294 --
295 -- >>> (-3,4) & both.nat *~ 2
296 -- (-3,8)
297 --
298 -- And we can then convert from a 'Natural' to an 'Integer'.
299 --
300 -- >>> 5 ^. remit nat -- :: Natural
301 -- 5
302 --
303 -- Similarly we can use a 'Prism' to 'traverse' the left half of an 'Either':
304 --
305 -- >>> Left "hello" & _left %~ length
306 -- Left 5
307 --
308 -- or to construct an 'Either':
309 --
310 -- >>> 5^.remit _left
311 -- Left 5
312 --
313 -- such that if you query it with the 'Prism', you will get your original input back.
314 --
315 -- >>> 5^.remit _left ^? _left
316 -- Just 5
317 --
318 -- Another interesting way to think of a 'Prism' is as the categorical dual of a 'Lens'
319 -- -- a /co/-'Lens', so to speak. This is what permits the construction of 'outside'.
320 type Prism s t a b = forall p f. (Prismatic p, Applicative f) => p a (f b) -> p s (f t)
321
322 -- | A 'Simple' 'Prism'
323 type Prism' s a = Prism s s a a
324
325 -------------------------------------------------------------------------------
3ce55f4 @ekmett Added 'Control.Lens.Equality'
authored
326 -- Equality
327 -------------------------------------------------------------------------------
328
329 -- | A witness that @(a ~ s, b ~ t)@
330 type Equality s t a b = forall p f. p a (f b) -> p s (f t)
331
332 -- | A 'Simple' 'Equality'
333 type Equality' s a = Equality s s a a
334
335 -------------------------------------------------------------------------------
6be7786 @ekmett Factoring out Control.Lens.Type
authored
336 -- Getters
337 -------------------------------------------------------------------------------
338
339 -- | A 'Getter' describes how to retrieve a single value in a way that can be
340 -- composed with other lens-like constructions.
341 --
342 -- Unlike a 'Lens' a 'Getter' is read-only. Since a 'Getter'
343 -- cannot be used to write back there are no lens laws that can be applied to
344 -- it. In fact, it is isomorphic to an arbitrary function from @(a -> s)@.
345 --
346 -- Moreover, a 'Getter' can be used directly as a 'Control.Lens.Fold.Fold',
347 -- since it just ignores the 'Applicative'.
348 type Getter s a = forall f. Gettable f => (a -> f a) -> s -> f s
349
350 -- | Every 'IndexedGetter' is a valid 'Control.Lens.Fold.IndexedFold' and 'Getter'.
351 type IndexedGetter i s a = forall p f. (Indexable i p, Gettable f) => p a (f a) -> s -> f s
352
353 --------------------------
354 -- Folds
355 --------------------------
356
357 -- | A 'Fold' describes how to retrieve multiple values in a way that can be composed
358 -- with other lens-like constructions.
359 --
360 -- A @'Fold' s a@ provides a structure with operations very similar to those of the 'Foldable'
361 -- typeclass, see 'foldMapOf' and the other 'Fold' combinators.
362 --
363 -- By convention, if there exists a 'foo' method that expects a @'Foldable' (f a)@, then there should be a
364 -- @fooOf@ method that takes a @'Fold' s a@ and a value of type @s@.
365 --
366 -- A 'Getter' is a legal 'Fold' that just ignores the supplied 'Monoid'
367 --
368 -- Unlike a 'Control.Lens.Traversal.Traversal' a 'Fold' is read-only. Since a 'Fold' cannot be used to write back
369 -- there are no lens laws that apply.
370 type Fold s a = forall f. (Gettable f, Applicative f) => (a -> f a) -> s -> f s
371
372 -- | Every 'IndexedFold' is a valid 'Control.Lens.Fold.Fold'.
373 type IndexedFold i s a = forall p f.
374 (Indexable i p, Applicative f, Gettable f) => p a (f a) -> s -> f s
375
3ce55f4 @ekmett Added 'Control.Lens.Equality'
authored
376
6be7786 @ekmett Factoring out Control.Lens.Type
authored
377 -------------------------------------------------------------------------------
378 -- Actions
379 -------------------------------------------------------------------------------
380
381 -- | An 'Action' is a 'Getter' enriched with access to a 'Monad' for side-effects.
382 --
383 -- Every 'Getter' can be used as an 'Action'
384 --
385 -- You can compose an 'Action' with another 'Action' using ('Prelude..') from the @Prelude@.
386 type Action m s a = forall f r. Effective m r f => (a -> f a) -> s -> f s
387
388 -- | An 'IndexedAction' is an 'IndexedGetter' enriched with access to a 'Monad' for side-effects.
389 --
390 -- Every 'Getter' can be used as an 'Action'
391 --
392 -- You can compose an 'Action' with another 'Action' using ('Prelude..') from the @Prelude@.
393 type IndexedAction i m s a = forall p f r. (Indexable i p, Effective m r f) => p a (f a) -> s -> f s
394
395 -------------------------------------------------------------------------------
396 -- MonadicFolds
397 -------------------------------------------------------------------------------
398
399 -- | A 'MonadicFold' is a 'Fold' enriched with access to a 'Monad' for side-effects.
400 --
401 -- Every 'Fold' can be used as a 'MonadicFold', that simply ignores the access to the 'Monad'.
402 --
403 -- You can compose a 'MonadicFold' with another 'MonadicFold' using ('Prelude..') from the @Prelude@.
404 type MonadicFold m s a = forall f r. (Effective m r f, Applicative f) => (a -> f a) -> s -> f s
405
406 -- | An 'IndexedMonadicFold' is an 'IndexedFold' enriched with access to a 'Monad' for side-effects.
407 --
408 -- Every 'IndexedFold' can be used as an 'IndexedMonadicFold', that simply ignores the access to the 'Monad'.
409 --
410 -- You can compose an 'IndexedMonadicFold' with another 'IndexedMonadicFold' using ('Prelude..') from the @Prelude@.
411 type IndexedMonadicFold i m s a = forall p f r. (Indexable i p, Effective m r f, Applicative f) => p a (f a) -> s -> f s
412
413 -------------------------------------------------------------------------------
414 -- Simple Overloading
415 -------------------------------------------------------------------------------
416
417 -- | A 'Simple' 'Lens', 'Simple' 'Traversal', ... can
418 -- be used instead of a 'Lens','Traversal', ...
419 -- whenever the type variables don't change upon setting a value.
420 --
421 -- @
422 -- 'Data.Complex.Lens.imaginary' :: 'Simple' 'Lens' ('Data.Complex.Complex' a) a
fe2037f @ehird Correct Control.Lens.Type.Simple documentation
ehird authored
423 -- 'Data.List.Lens._head' :: 'Simple' 'IndexedTraversal' Int [a] a
6be7786 @ekmett Factoring out Control.Lens.Type
authored
424 -- @
425 --
426 -- Note: To use this alias in your own code with @'LensLike' f@ or
427 -- 'Setter', you may have to turn on @LiberalTypeSynonyms@.
428 --
429 -- This is commonly abbreviated as a \"prime\" marker, /e.g./ 'Lens'' = 'Simple' 'Lens'.
430 type Simple f s a = f s s a a
431
432 -- | @type 'LensLike' f s t a b = 'Overloading' (->) (->) f s t a b@
433 type Overloading p q f s t a b = p a (f b) -> q s (f t)
434
435 -- | @type 'Overloading'' p q f s a = 'Simple' ('Overloading' p q f) s a@
436 type Overloading' p q f s a = Overloading p q f s s a a
437
438 -- |
439 -- Many combinators that accept a 'Lens' can also accept a
440 -- 'Traversal' in limited situations.
441 --
442 -- They do so by specializing the type of 'Functor' that they require of the
443 -- caller.
444 --
445 -- If a function accepts a @'LensLike' f s t a b@ for some 'Functor' @f@,
446 -- then they may be passed a 'Lens'.
447 --
448 -- Further, if @f@ is an 'Applicative', they may also be passed a
449 -- 'Traversal'.
450 type LensLike f s t a b = (a -> f b) -> s -> f t
451
452 -- | @type 'LensLike'' f = 'Simple' ('LensLike' f)@
453 type LensLike' f s a = LensLike f s s a a
454
455 -- | Convenient alias for constructing indexed lenses and their ilk
456 type IndexedLensLike p f s t a b = p a (f b) -> s -> f t
457
458 -- | Convenient alias for constructing simple indexed lenses and their ilk
459 type IndexedLensLike' p f s a = p a (f a) -> s -> f s
Something went wrong with that request. Please try again.