HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Moduleoptics-0.4.2.1Haskell2010

Optics

This library makes it possible to define and use Lenses, Traversals, Prisms and other optics, using an abstract interface.

  • 90 types
  • 45 classes
  • 384 values
  • Packageoptics-0.4.2.1
  • Exports531
  • LanguageHaskell2010
  • LicenceBSD-3-Clause
  • SourceOptics.hs

Introduction

0 declarations

Read on for a general introduction to the notion of optics, or if you are familiar with them already, you may wish to jump ahead to the "What is the abstract interface?" section below in Optics#abstract.

What are optics?

An optic is a first-class, composable notion of substructure. As a highly abstract concept, the idea can be approached by considering several examples of optics and understanding their common features. What are the possible relationships between some "outer" type S and some "inner" type A?

(For simplicity we will initially ignore the possibility of type-changing update operations, which change A to some other type B and hence change S to some other type T. These are fully supported by the library, at the cost of some extra type parameters.)

Optics.Iso: isomorphisms

First, S and A may be isomorphic, i.e. there exist mutually inverse functions to convert S -> A and A -> S. This is a somewhat trivial notion of substructure: A is just another way to represent "all of S".

An Iso' S A is an isomorphism between S and A, with the conversion functions given by view and review. For example, given

newtype Age = Age Int

there is an isomorphism between the newtype and its representation:

       coerced :: Iso' Age Int
view   coerced :: Age -> Int
review coerced :: Int -> Age
Optics.Lens: generalised fields

If S is a simple product type (i.e. it has a single constructor with one or more fields), A may be a single field of S. More generally, A may be "part of S" in the sense that S is isomorphic to the pair (A,C) for some type C representing the other fields. In this case, there is a projection function S -> A for getting the value of the field, but the update function (setting the value of the field) requires the "rest of S" and so has type A -> S -> S.

A Lens' S A captures the structure of A being a field of S, with the projection function given by view and the update function by set. For example, for the pair type (X,Y) there are lenses for each component:

     _1 :: Lens' (X,Y) X
     _2 :: Lens' (X,Y) Y
view _1 :: (X,Y) -> X
set  _2 :: Y -> (X,Y) -> (X,Y)

(Note that the update function could arguably have the more precise type A -> C -> S, since we do not expect the result of setting a field to depend on the previous value of the field. However, making C explicit turns out to be awkward, so instead we impose laws to require that the result of setting the field depends only on C, and, more generally, that the lens behaves as we would expect.)

Optics.Prism: generalised constructors

If S is a simple sum type (i.e. it has one or more constructors, each with a single field), A may be the type of the field for a single constructor of S. More generally, S may be isomorphic to the disjoint union Either D A for some type D representing the other constructors. In this case, projecting out A from S (pattern-matching on the constructor) may fail, so it has type S -> Maybe A. In the reverse direction we have a function of type A -> S representing the constructor itself.

A Prism' S A captures the structure of A being a constructor of S, with the partial projection function given by preview and the constructor function given by review. For example, for the type Either X Y there is a prism for each constructor:

        _Left  :: Prism' (Either X Y) X
        _Right :: Prism' (Either X Y) Y
preview _Left  :: Either X Y -> Maybe X
review  _Right :: Y -> Either X Y
Optics.Traversal: multiple substructures

Alternatively, S may "contain" the substructure A a variable number of times. In this case, the projection function extracts the (possibly zero or many) elements so has type S -> [A], while the update function may take different values for different elements so has type (A -> A) -> S -> S (though in fact more general formulations are possible).

A Traversal' S A captures the structure of A being contained in S perhaps multiple times, with the list of values given by toListOf and the update function given by over . For example, for the type Maybe X there is a traversal that may return zero or one element:

         traversed :: Traversal' (Maybe X) X
toListOf traversed :: Maybe X -> [X]
over     traversed :: (X -> X) -> Maybe X -> Maybe X

(In fact, traversals of at most one element are known as affine traversals, see Optics.AffineTraversal.)

In general

So far we have seen four different kinds of optic or "notions of substructure", and many more are possible. Observe the important properties they have in common:

  • There are subtyping relationships between different optic kinds. Any isomorphism is trivially a lens and a prism (with no other fields or constructors, respectively). Any lens is a traversal (where the list of elements is always a singleton list), and any prism is also a traversal (where there will be zero or one element depending on whether the constructor matches). This was implicit in the fact that we used the same operators in multiple cases: view gives the projection function of both an isomorphism and a lens, but cannot be applied to a traversal.

  • Optics can be composed. If S is isomorphic to U and U is isomorphic to A then S is isomorphic to A, and similarly for other optic kinds.

  • Composition and subtyping interact: a lens and a prism can be composed, by first thinking of them as traversals using the subtyping relationship. That is, if S has a field U, and U has a constructor A, then S contains zero or one As that we can pick out with a traversal (but in general there is neither a lens from S to A nor a prism).

  • Each optic kind can be described by certain operations it enables. For example lenses support projection and update, while prisms support partial projection and construction.

  • Optics are subject to laws, which are necessary for the operations to make sense.

The point of the optics library is to capture this common pattern.

What is the abstract interface?

A key principle behind this library is the belief that optics are useful as an abstract concept, and that the purpose of types is to capture abstract concepts and make them useful. The programmer using optics should be able to think in terms of the abstract interface, rather than the details of the implementation, and implementation choices should (as far as possible) not dictate the interface.

Each optic kind is identified by a "tag type" (such as A_Lens), which is an empty data type. The type of the actual optics (such as Lens) is obtained by applying the Optic newtype wrapper to the tag type.

type Lens  s t a b = Optic  A_Lens NoIx s t a b
type Lens' s   a   = Optic' A_Lens NoIx s   a

NoIx as the second parameter to Optic indicates that the optic is not indexed. See the "Indexed optics" section below in Optics#indexed for further discussion of indexed optics.

The details of the internal implementation of Optic are hidden behind an abstraction boundary, so that the library can be used without needing to think about the particular implementation choices.

Specification of optics interfaces

Each different kind of optic is documented in a separate module describing its abstract interface, in a standard format with at least formation, introduction, elimination, and well-formedness sections. See "Optic kinds" below in Optics#optickinds for a list of these modules.

  • The formation sections contain type definitions. For example Optics.Lens defines:

    -- Type synonym for a type-modifying lens.
    type Lens s t a b = Optic A_Lens NoIx s t a b
    
  • The introduction sections describe the canonical way to construct each particular optic. Continuing with a Lens example:

    -- Build a lens from a getter and a setter.
    lens :: (s -> a) -> (s -> b -> t) :: Lens s t a b
    
  • Correspondingly, the elimination sections show how you can destruct the optic into the pieces from which it was constructed.

    -- A Lens is a Setter and a Getter, therefore you can specialise types to obtain
    view :: Lens s t a b -> s -> a
    set  :: Lens s t a b -> b -> s -> t
    
  • The computation rules tie introduction and elimination forms together. These rules are automatically fulfilled by the library (for well-formed optics).

    view (lens f g)   s ≡ f s
    set  (lens f g) a s ≡ g s a
    
  • The well-formedness sections describe the laws that each optic should obey. As far as possible, all optics provided by the library are well-formed, but in some cases this depends on invariants that cannot be expressed in types. Ill-formed optics might behave differently from what the computation rules specify.

    For example, a Lens should obey three laws, known as GetPut, PutGet and PutPut. See the Optics.Lens module for their definitions. The user of the lens introduction form must ensure that these laws are satisfied.

  • Some optic kinds have additional introduction forms, additional elimination forms or combinators sections, which give alternative ways to create and use optics of that kind. In principle these are expressible in terms of the canonical introduction and elimination rules.

  • The subtyping section gives the "tag type" (such as A_Lens), which in particular is accompanied by Is instances that define the subtyping relationship discussed in the following section.

Subtyping

There is a subtyping relationship between optics, implemented using typeclasses. The Is typeclass captures the property that one optic kind can be used as another, and the castOptic function can be used to explicitly cast between optic kinds. Is forms a partial order, represented in the graph below. For example, a lens can be used as a traversal, so there are arrows from Lens to Traversal (via AffineTraversal) and there is an instance of Is A_Lens A_Traversal.

Introduction forms (constructors) return a concrete optic kind, while elimination forms (destructors) are generally polymorphic in the optic kind they accept. This means that it is not normally necessary to explicitly cast between optic kinds. For example, we have

view :: Is k A_Getter => Optic' k is s a -> s -> a

so view can be used with isomorphisms or lenses, as these can be converted to a Getter.

If an explicit cast is needed, you can use castOptic. This arises when you use optics of different kinds in a context that requires them to have the same type. For example [folded, traversed] gives a type error (since A_Traversal is not A_Fold) but [folded, castOptic traversed] works.

The optic kind module (e.g. Optics.Lens) does not list all ways to construct or use particular the optic kind. For example, since a Lens is also a Traversal, a Fold etc, so you can use traverseOf, preview and many other combinators with lenses.

Subtype hierarchy

This graph gives an overview of the optic kinds and their subtype relationships:

Optics hierarchy

In addition to the optic kinds included in the diagram, there are also indexed variants such as IxLens, IxGetter, IxAffineTraversal, IxTraversal, IxAffineFold, IxFold and IxSetter. These are explained in more detail in the "Indexed optics" section below in Optics#indexed.

Composition

Since optics are not functions, they cannot be composed with the (.) operator. Instead there is a separate composition operator (%). The composition operator returns the common supertype of its arguments, or generates a type error if the composition does not make sense.

The optic kind resulting from a composition is the least upper bound (join) of the optic kinds being composed, if it exists. The JoinKinds class computes the least upper bound given two optic kind tags. For example the constraint 'JoinKinds A_Lens A_Prism k' makes GHC infer that k must be An_AffineTraversal.

The join does not exist for some pairs of optic kinds, which means that they cannot be composed. For example there is no optic kind above both Setter and Fold:

Example1 expression
:t mapped % folded......A_Setter cannot be composed with A_Fold...

The (.) operator from Control.Category cannot be used to compose optics either, because it would not support type-changing optics or composing optics of different kinds.

Comparison with lens

The lens package is the best known Haskell library for optics, and established many of the foundations on which the optics package builds (not least in quite a bit of code having been directly ported). It defines optics based on the van Laarhoven representation, where each optic kind is introduced as a transparent type synonym for a complex polymorphic type, for example:

type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t

In contrast, optics tries to preserve an abstraction boundary between the interface of optics and their implementation. Optic kinds are expressed directly in the types, as Optic is an opaque newtype:

type Lens s t a b = Optic A_Lens NoIx s t a b

The choice of representation of Optic is then an implementation detail, not essential for understanding the library. (In fact, optics uses the profunctor representation rather than the van Laarhoven representation; this affects the optic kinds and operations that can be conveniently supported, but not the essence of the design.)

Our design choice to use opaque rather than transparent abstractions leads to various consequences, both positive and negative, which are explored in the following subsections.

Advantages of the opaque design

Since the interface is deliberately chosen rather than to some extent determined by the implementation, we are free to choose a more restricted interface where doing so leads to conceptual simplicity. For example, in lens, the view function can be used with a Fold provided the result type has a Monoid instance, and the multiple targets of the Fold will be combined monoidally. This behaviour can be confusing, so in optics a Fold cannot be silently used as a Getter, and we prefer to have view work on Getters and define a separate foldOf operator for use on Folds. (But the gview function is available for users who may prefer otherwise.)

In general, opaque abstractions lead to better results from type inference (the optic kind is preserved in the inferred type):

Example1 expression
:t traversed % to nottraversed % to not  :: Traversable t => Optic A_Fold '[] (t Bool) (t Bool) Bool Bool

Error messages are domain-specific:

Example1 expression
set (to fst)......A_Getter cannot be used as A_Setter...

Composing incompatible optics yields a sensible error:

Example1 expression
sets map % to not......A_Setter cannot be composed with A_Getter...

Since Optic is a rank-1 type, it is easy to store optics in a datastructure:

Example1 expression
:t [folded, backwards_ folded][folded, backwards_ folded] :: Foldable f => [Fold (f a) a]

It is possible to define aliases for optics without the monomorphism restriction spoiling the fun:

Example1 expression
let { myoptic = _1; p = ('x','y') } in (view myoptic p, set myoptic 'c' p)('x',('c','y'))

Finally, having an abstract interface gives more freedom of choice in the internal implementation. If there is a compelling reason to switch to an alternative representation, one can in principle do so without changing the interface.

Disadvantages of the opaque design

Since Optic is a newtype, other libraries that wish to define optics must depend upon its definition. In contrast, with a transparent representation, and since the van Laarhoven representations of lenses and traversals depend only on definitions from base, it is possible for libraries to define them without any extra library dependencies (although this does not hold for more advanced optic kinds such as prisms or indexed optics). To address this, the present library is split into a package optics-core, which has a minimal dependency footprint intended for use in libraries, and the "batteries-included" optics package for use in applications.

It is something of an amazing fact that the composition operator for transparent optics is just function composition. Moreover, since Haskell uses (.) for function composition, lens is able to support a pseudo-OOP syntax. In contrast, optics must use a different composition operator (%). Optic does not quite form a Category, thanks to type-changing optics.

Rather than emerging naturally from the definitions, opportunities for polymorphism have to be identified in advance and explicitly introduced using type classes. Similarly, the set of optic kinds and the subtyping relationships between them must be fixed in advance, and cannot be added to in downstream libraries. Thus in a sense the opaque approach is more restrictive than the transparent one. There are cases in lens where the types work out nicely and permit abstraction-breaking-but-convenient shortcuts, such as applying a Traversal as a traverse-like function, whereas optics requires a call to traverseOf.

More specific differences

The sections above set out the major conceptual differences from the lens package, and their advantages and disadvantages. Some more specific design differences, which may be useful for comparison or porting code between the libraries. This list is no doubt incomplete.

  • The composition operator is (%) rather than (.) and is defined as infixl 9 instead of infixr 9.

  • Fewer operators are provided, and some of them are not exported from the main Optics module. Import Optics.State.Operators if you want them.

  • The view function and corresponding (^.) operator work only for Getters and have a more restricted type. The equivalent for Folds is foldOf, and you can use preview for AffineFolds. Alternatively you can use gview which is more compatible with view from lens, but it uses a type class to choose between view, preview and foldOf.

  • Indexed optics are rather different, as described in the "Indexed optics" section below in Optics#indexed. All ordinary optics are "index-preserving", so there is no separate notion of an index-preserving optic.

  • Each provides indexed traversals.

  • firstOf from lens is replaced by headOf.

  • concatOf from lens is omitted in favour of the more general foldOf.

  • set' is a strict version of set, not set for type-preserving optics.

  • Numbered lenses for accessing fields of tuples positionally are provided only up to _9, rather than _19.

  • There are four variants of backwards for (indexed) Traversals and Folds: backwards, backwards_, ibackwards and ibackwards_.

  • There is no Traversal1 and Fold1.

  • There are affine variants of (indexed) traversals and folds (AffineTraversal, AffineFold, IxAffineTraversal and IxAffineFold). An affine optic targets at most one value. Composing a Lens with a Prism produces an AffineTraversal, so for example matching (_1 % _Left) is well-typed.

  • Functions ifiltered and indices are defined as optic combinators due to restrictions of internal representation.

  • We can't use traverse as an optic directly. Instead there is a Traversal called traversed. Similarly traverseOf must be used to apply a Traversal, rather than simply using it as a function.

  • The re combinator produces a different optic kind depending on the kind of the input Iso, for example Review reverses to Getter while a reversed Iso is still an Iso. Thus there is no separate from combinator for reversing Isos.

  • singular (isingular for indexed optics) doesn't produce a partial lens that might fail with a runtime error, but an affine traversal.

  • <> cannot be used to combine Folds, so summing should be used instead (see the "Monoid structures" section below in Optics#monoids).

Other resources

Talks
  • (2020-10) User Friendly Optics - a talk about the optics library in comparison to the lens library by Andrzej Rybczak

Articles
Libraries
  • The lens package by Edward Kmett and contributors

Using the library

20 declarations

To get started, you can just add optics as a dependency to your .cabal file, and then:

import Optics

If you are writing a library for which it is important to keep the dependency footprint minimal, you may wish to depend upon optics-core instead (and perhaps optics-extra or optics-th), and then:

import Optics.Core
newtypenewtype Optic (k :: OpticKind) (is :: IxList) s t a b
#

Wrapper newtype for the whole family of optics.

The first parameter k identifies the particular optic kind (e.g. A_Lens or A_Traversal).

The parameter is is a list of types available as indices. This will typically be NoIx for unindexed optics, or WithIx for optics with a single index. See the "Indexed optics" section of the overview documentation in the Optics module of the main optics package for more details.

The parameters s and t represent the "big" structure, whereas a and b represent the "small" structure.

Instances1IsLabel
classclass is ~ '[i] => HasSingleIndex (is :: IxList) i
#

Generate sensible error messages in case a user tries to pass either an unindexed optic or indexed optic with unflattened indices where indexed optic with a single index is expected.

Instances7HasSingleIndex, …
  • (TypeError ('Text "Indexed optic is expected"), '[] ~ '[i]) => HasSingleIndex '[] iDefined in optics-core-0.4.1.1 · Optics.Internal.Indexed
  • HasSingleIndex '[i] iDefined in optics-core-0.4.1.1 · Optics.Internal.Indexed
  • (TypeError ('Text "Use (<%>) or icompose to combine indices of type " ':<>: ShowTypes is), is ~ '[i1, i2], is ~ '[i]) => HasSingleIndex '[i1, i2] iDefined in optics-core-0.4.1.1 · Optics.Internal.Indexed
  • (TypeError ('Text "Use icompose3 to combine indices of type " ':<>: ShowTypes is), is ~ '[i1, i2, i3], is ~ '[i]) => HasSingleIndex '[i1, i2, i3] iDefined in optics-core-0.4.1.1 · Optics.Internal.Indexed
  • (TypeError ('Text "Use icompose4 to combine indices of type " ':<>: ShowTypes is), is ~ '[i1, i2, i3, i4], is ~ '[i]) => HasSingleIndex '[i1, i2, i3, i4] iDefined in optics-core-0.4.1.1 · Optics.Internal.Indexed
  • (TypeError ('Text "Use icompose5 to flatten indices of type " ':<>: ShowTypes is), is ~ '[i1, i2, i3, i4, i5], is ~ '[i]) => HasSingleIndex '[i1, i2, i3, i4, i5] iDefined in optics-core-0.4.1.1 · Optics.Internal.Indexed
  • (TypeError ('Text "Use icomposeN to flatten indices of type " ':<>: ShowTypes is), is ~ (i1 ': i2 ': i3 ': i4 ': i5 ': i6 ': is'), is ~ '[i]) => HasSingleIndex (i1 ': i2 ': i3 ': i4 ': i5 ': i6 ': is') iDefined in optics-core-0.4.1.1 · Optics.Internal.Indexed
classclass NonEmptyIndices (is :: IxList)
#

Check whether a list of indices is not empty and generate sensible error message if it's not.

Instances2NonEmptyIndices
value(%)
  1. :: (JoinKinds k l m, AppendIndices is js ks)
  2. => Optic k is s t u v
  3. -> Optic l js u v a b
  4. -> Optic m ks s t a b
#

Compose two optics of compatible flavours.

Returns an optic of the appropriate supertype. If either or both optics are indexed, the composition preserves all the indices.

value(%%)
  1. :: AppendIndices is js ks
  2. => Optic k is s t u v
  3. -> Optic k js u v a b
  4. -> Optic k ks s t a b
#

Compose two optics of the same flavour.

Normally you can simply use (%) instead, but this may be useful to help type inference if the type of one of the optics is otherwise under-constrained.

value(%&)
  1. :: Optic k is s t a b
  2. -> Optic k is s t a b -> Optic l js s' t' a' b'
  3. -> Optic l js s' t' a' b'
#

Flipped function application, specialised to optics and binding tightly.

Useful for post-composing optics transformations:

Example1 expression
toListOf (ifolded %& ifiltered (\i s -> length s <= i)) ["", "a","abc"]["","a"]
typetype Optic' (k :: OpticKind) (is :: IxList) s a = Optic k is s s a a
#

Common special case of Optic where source and target types are equal.

Here, we need only one "big" and one "small" type. For lenses, this means that in the restricted form we cannot do type-changing updates.

valuecastOptic
  1. :: Is srcKind destKind
  2. => Optic srcKind is s t a b
  3. -> Optic destKind is s t a b
#

Explicit cast from one optic flavour to another.

The resulting optic kind is given in the first type argument, so you can use TypeApplications to set it. For example

 castOptic @A_Lens o

turns o into a Lens.

This is the identity function, modulo some constraint jiggery-pokery.

classclass Is (k :: OpticKind) (l :: OpticKind) where
#

Subtyping relationship between kinds of optics.

An instance of Is k l means that any Optic k can be used as an Optic l. For example, we have an Is A_Lens A_Traversal instance, but not Is A_Traversal A_Lens.

This class needs instances for all possible combinations of tags.

Instances38Is, …
classclass JoinKinds (k :: OpticKind) (l :: OpticKind) (m :: OpticKind) | k l -> m where
#

Computes the least upper bound of two optics kinds.

In presence of a JoinKinds k l m constraint Optic m represents the least upper bound of an Optic k and an Optic l. This means in particular that composition of an Optic k and an Optic k will yield an Optic m.

Instances105JoinKinds, …
classclass AppendIndices (xs :: IxList) (ys :: IxList) (ks :: IxList) | xs ys -> ks where
#

In pseudo (dependent-)Haskell, provide a witness

foldr f (foldr f init xs) ys = foldr f init (ys ++ xs)
   where f = (->)
Instances3AppendIndices
  • xs ~ zs => AppendIndices xs '[] zsDefined in optics-core-0.4.1.1 · Optics.Internal.Optic.TypeLevel

    If the second list is empty, we can pick the first list even if nothing is known about it.

  • ys ~ zs => AppendIndices '[] ys zsDefined in optics-core-0.4.1.1 · Optics.Internal.Optic.TypeLevel
  • AppendIndices xs ys ks => AppendIndices (x ': xs) ys (x ': ks)Defined in optics-core-0.4.1.1 · Optics.Internal.Optic.TypeLevel
familytype family Curry (xs :: IxList) y where
#

Curry a type-level list.

In pseudo (dependent-)Haskell:

Curry xs y = foldr (->) y xs

Equations

classclass CurryCompose (xs :: IxList) where
#

Class that is inhabited by all type-level lists xs, providing the ability to compose a function under Curry xs.

Methods

  • composeN :: (i -> j) -> Curry xs i -> Curry xs j

    Compose a function under Curry xs. This generalises (.) (aka fmap for (->)) to work for curried functions with one argument for each type in the list.

Instances2CurryCompose
  • CurryCompose '[]Defined in optics-core-0.4.1.1 · Optics.Internal.Optic.TypeLevel
  • CurryCompose xs => CurryCompose (x ': xs)Defined in optics-core-0.4.1.1 · Optics.Internal.Optic.TypeLevel
typetype IxList = [Type]
#

A list of index types, used for indexed optics.

typetype NoIx = '[]
#

An alias for an empty index-list

typetype WithIx i = '[i]
#

Singleton index list

value(&) :: a -> (a -> b) -> b
#

& is a reverse application operator. This provides notational convenience. Its precedence is one higher than that of the forward application operator $, which allows & to be nested in $.

This is a version of flip id, where id is specialized from a -> a to (a -> b) -> (a -> b) which by the associativity of (->) is (a -> b) -> a -> b. flipping this yields a -> (a -> b) -> b which is the type signature of &

Examples
Example1 expression
5 & (+1) & show"6"
Example1 expression
sqrt $ [1 / n^2 | n <- [1..1000]] & sum & (*6)3.1406380562059946
value(<&>) :: Functor f => f a -> (a -> b) -> f b
#

Flipped version of <$>.

(<&>) = flip fmap
Examples

Apply (+1) to a list, a Just and a Right:

Example1 expression
Just 2 <&> (+1)Just 3
Example1 expression
[1,2,3] <&> (+1)[2,3,4]
Example1 expression
Right 3 <&> (+1)Right 4

Optic kinds

datadata A_Lens
#

Tag for a lens.

Instances38ReversibleOptic, Is, ArrowOptic, ViewableOptic, PermeableOptic, JoinKinds, …
valueatraversalVL :: AffineTraversalVL s t a b -> AffineTraversal s t a b
#

Build an affine traversal from the van Laarhoven representation.

Example:

Example1 expression
:{azSnd = atraversalVL $ \point f ab@(a, b) ->  if a >= 'a' && a <= 'z'  then (a, ) <$> f b  else point ab:}
Example1 expression
preview azSnd ('a', "Hi")Just "Hi"
Example1 expression
preview azSnd ('@', "Hi")Nothing
Example1 expression
over azSnd (++ "!!!") ('f', "Hi")('f',"Hi!!!")
Example1 expression
set azSnd "Bye" ('Y', "Hi")('Y',"Hi")
valueheadOf :: Is k A_Fold => Optic' k is s a -> s -> Maybe a
#

Retrieve the first entry of a Fold.

Example1 expression
headOf folded [1..10]Just 1
Example1 expression
headOf each (1,2)Just 1
valuetoListOf :: Is k A_Fold => Optic' k is s a -> s -> [a]
#

Fold to a list.

Example1 expression
toListOf (_1 % folded % _Right) ([Right 'h', Left 5, Right 'i'], "bye")"hi"
datadata A_Traversal
#

Tag for a traversal.

Instances31Is, ViewableOptic, PermeableOptic, JoinKinds, IxOptic, ToReadOnly, …
valuelensVL :: LensVL s t a b -> Lens s t a b
#

Build a lens from the van Laarhoven representation.

valueadjoin
  1. :: (Is k A_Traversal, Is l A_Traversal)
  2. => Optic' k is s a
  3. -> Optic' l js s a
  4. -> Traversal' s a
#

Combine two disjoint traversals into one.

Example1 expression
over (_1 % _Just `adjoin` _2 % _Right) not (Just True, Right False)(Just False,Right True)

Note: if the argument traversals are not disjoint, the result will not respect the Traversal laws, because it will visit the same element multiple times. See section 7 of Understanding Idiomatic Traversals Backwards and Forwards by Bird et al. for why this is illegal.

Example2 expressions
view (partsOf (each `adjoin` _1)) ('x','y')"xyx"set (partsOf (each `adjoin` _1)) "abc" ('x','y')('c','b')

For the Fold version see summing.

valueboth :: Bitraversable r => Traversal (r a a) (r b b) a b
#

Traverse both parts of a Bitraversable container with matching types.

Note: for traversing a pair or an Either it's better to use each and chosen respectively to reduce potential for bugs due to too much polymorphism.

Example1 expression
(1,2) & both %~ (*10)(10,20)
Example1 expression
over both length ("hello","world")(5,5)
Example1 expression
foldOf both ("hello","world")"helloworld"
valuefailover
  1. :: Is k A_Traversal
  2. => Optic k is s t a b
  3. -> a -> b
  4. -> s
  5. -> Maybe t
#

Try to map a function over this Traversal, returning Nothing if the traversal has no targets.

Example1 expression
failover (element 3) (*2) [1,2]Nothing
Example1 expression
failover _Left (*2) (Right 4)Nothing
Example1 expression
failover _Right (*2) (Right 4)Just (Right 8)
valuepartsOf :: Is k A_Traversal => Optic k is s t a a -> Lens s t [a] [a]
#

partsOf turns a Traversal into a Lens.

Note: You should really try to maintain the invariant of the number of children in the list.

Example1 expression
('a','b','c') & partsOf each .~ ['x','y','z']('x','y','z')

Any extras will be lost. If you do not supply enough, then the remainder will come from the original structure.

Example1 expression
('a','b','c') & partsOf each .~ ['w','x','y','z']('w','x','y')
Example1 expression
('a','b','c') & partsOf each .~ ['x','y']('x','y','c')
Example1 expression
('b', 'a', 'd', 'c') & partsOf each %~ sort('a','b','c','d')

So technically, this is only a Lens if you do not change the number of results it returns.

valuerewriteMOf
  1. :: (Is k A_Traversal, Monad m)
  2. => Optic k is a b a b
  3. -> b -> m (Maybe a)
  4. -> a
  5. -> m b
#

Rewrite by applying a monadic rule everywhere you recursing with a user-specified Traversal.

Ensures that the rule cannot be applied anywhere in the result.

typetype TraversalVL s t a b = forall (f :: Type -> Type). Applicative f => (a -> f b) -> s -> f t
#

Type synonym for a type-modifying van Laarhoven traversal.

datadata An_AffineTraversal
#

Tag for an affine traversal.

Instances33Is, ArrowOptic, ViewableOptic, PermeableOptic, JoinKinds, IxOptic, …
valuesumming
  1. :: (Is k A_Fold, Is l A_Fold)
  2. => Optic' k is s a
  3. -> Optic' l js s a
  4. -> Fold s a
#

Return entries of the first Fold, then the second one.

Example1 expression
toListOf (_1 % ix 0 `summing` _2 % ix 1) ([1,2], [4,7,1])[1,7]

For the traversal version see adjoin.

valuefailing
  1. :: (Is k A_Fold, Is l A_Fold)
  2. => Optic' k is s a
  3. -> Optic' l js s a
  4. -> Fold s a
#

Try the first Fold. If it returns no entries, try the second one.

Example2 expressions
toListOf (ix 1 `failing` ix 0) [4,7][7]toListOf (ix 1 `failing` ix 0) [4][4]
datadata A_Setter
#

Tag for a setter.

Instances17Is, JoinKinds, IxOptic, …
valueover :: Is k A_Setter => Optic k is s t a b -> (a -> b) -> s -> t
#

Apply a setter as a modifier.

valueover' :: Is k A_Setter => Optic k is s t a b -> (a -> b) -> s -> t
#

Apply a setter as a modifier, strictly.

TODO DOC: what exactly is the strictness property?

Example:

 f :: Int -> (Int, a) -> (Int, a)
 f k acc
   | k > 0     = f (k - 1) $ over' _1 (+1) acc
   | otherwise = acc

runs in constant space, but would result in a space leak if used with over.

Note that replacing $ with $! or _1 with _1' (which amount to the same thing) doesn't help when over is used, because the first coordinate of a pair is never forced.

valuerewriteOf :: Is k A_Setter => Optic k is a b a b -> (b -> Maybe a) -> a -> b
#

Rewrite by applying a rule everywhere you can. Ensures that the rule cannot be applied anywhere in the result:

propRewriteOf l r x = all (Data.Just.isNothing . r) (universeOf l (rewriteOf l r x))

Usually transformOf is more appropriate, but rewriteOf can give better compositionality. Given two single transformations f and g, you can construct \a -> f a <|> g a which performs both rewrites until a fixed point.

valueset :: Is k A_Setter => Optic k is s t a b -> b -> s -> t
#

Apply a setter.

set o v ≡ over o (const v)
Example1 expression
set _1 'x' ('y', 'z')('x','z')
valueset' :: Is k A_Setter => Optic k is s t a b -> b -> s -> t
#

Apply a setter, strictly.

TODO DOC: what exactly is the strictness property?

valuesets :: ((a -> b) -> s -> t) -> Setter s t a b
#

Build a setter from a function to modify the element(s), which must respect the well-formedness laws.

valuetransformOf :: Is k A_Setter => Optic k is a b a b -> (b -> b) -> a -> b
#

Transform every element by recursively applying a given Setter in a bottom-up manner.

datadata A_Review
#

Tag for a review.

Instances14ReversibleOptic, Is, JoinKinds, MappingOptic, MappedOptic, ReversedOptic, …
valuereview :: Is k A_Review => Optic' k is t b -> b -> t
#

Retrieve the value targeted by a Review.

Example1 expression
review _Left "hi"Left "hi"
valueunto :: (b -> t) -> Review t b
#

An analogue of to for reviews.

datadata A_ReversedPrism
#

Tag for a reversed prism.

Instances29ReversibleOptic, Is, ViewableOptic, JoinKinds, ToReadOnly, MappingOptic, …
datadata A_Prism
#

Tag for a prism.

Instances41ReversibleOptic, Is, ArrowOptic, ViewableOptic, PermeableOptic, JoinKinds, …
valuenearly :: a -> (a -> Bool) -> Prism' a ()
#

This Prism compares for approximate equality with a given value and a predicate for testing, an example where the value is the empty list and the predicate checks that a list is empty (same as _Empty with the AsEmpty list instance):

Example2 expressions
nearly [] null # ()[][1,2,3,4] ^? nearly [] nullNothing
nearly [] null :: Prism' [a] ()

To comply with the Prism laws the arguments you supply to nearly a p are somewhat constrained.

We assume p x holds iff x ≡ a. Under that assumption then this is a valid Prism.

This is useful when working with a type where you can test equality for only a subset of its values, and the prism selects such a value.

valueonly :: Eq a => a -> Prism' a ()
#

This Prism compares for exact equality with a given value.

Example1 expression
only 4 # ()4
Example1 expression
5 ^? only 4Nothing
valueprism :: (b -> t) -> (s -> Either t a) -> Prism s t a b
#

Build a prism from a constructor and a matcher, which must respect the well-formedness laws.

If you want to build a Prism from the van Laarhoven representation, use prismVL from the optics-vl package.

valueprism' :: (b -> s) -> (s -> Maybe a) -> Prism s s a b
#

This is usually used to build a Prism', when you have to use an operation like cast which already returns a Maybe.

datadata A_ReversedLens
#

Tag for a reversed lens.

Instances13ReversibleOptic, Is, JoinKinds, MappingOptic, MappedOptic, ReversedOptic, …
valuealongside
  1. :: (Is k A_Lens, Is l A_Lens)
  2. => Optic k is s t a b
  3. -> Optic l js s' t' a' b'
  4. -> Lens (s, s') (t, t') (a, a') (b, b')
#

Make a Lens from two other lenses by executing them on their respective halves of a product.

Example1 expression
(Left 'a', Right 'b') ^. alongside chosen chosen('a','b')
Example1 expression
(Left 'a', Right 'b') & alongside chosen chosen .~ ('c','d')(Left 'c',Right 'd')
valuelens :: (s -> a) -> (s -> b -> t) -> Lens s t a b
#

Build a lens from a getter and a setter, which must respect the well-formedness laws.

If you want to build a Lens from the van Laarhoven representation, use lensVL.

valueunited :: Lens' a ()
#

We can always retrieve a () from any type.

Example1 expression
view united "hello"()
Example1 expression
set united () "hello""hello"
typetype LensVL s t a b = forall (f :: Type -> Type). Functor f => (a -> f b) -> s -> f t
#

Type synonym for a type-modifying van Laarhoven lens.

typetype LensVL' s a = LensVL s s a a
#

Type synonym for a type-preserving van Laarhoven lens.

valueitoListOf
  1. :: (Is k A_Fold, HasSingleIndex is i)
  2. => Optic' k is s a
  3. -> s
  4. -> [(i, a)]
#

Fold with index to a list.

Example1 expression
itoListOf (folded % ifolded) ["abc", "def"][(0,'a'),(1,'b'),(2,'c'),(0,'d'),(1,'e'),(2,'f')]

Note: currently indexed optics can be used as non-indexed.

Example1 expression
toListOf (folded % ifolded) ["abc", "def"]"abcdef"
valueilensVL :: IxLensVL i s t a b -> IxLens i s t a b
#

Build an indexed lens from the van Laarhoven representation.

valueiadjoin
  1. :: (Is k A_Traversal, Is l A_Traversal, HasSingleIndex is i)
  2. => Optic' k is s a
  3. -> Optic' l is s a
  4. -> IxTraversal' i s a
#

Combine two disjoint indexed traversals into one.

Example1 expression
iover (_1 % itraversed `iadjoin` _2 % itraversed) (+) ([0, 0, 0], (3, 5))([0,1,2],(3,8))

Note: if the argument traversals are not disjoint, the result will not respect the IxTraversal laws, because it will visit the same element multiple times. See section 7 of Understanding Idiomatic Traversals Backwards and Forwards by Bird et al. for why this is illegal.

Example2 expressions
iview (ipartsOf (each `iadjoin` each)) ("x","y")([0,1,0,1],["x","y","x","y"])iset (ipartsOf (each `iadjoin` each)) (const ["a","b","c","d"]) ("x","y")("c","d")

For the IxFold version see isumming.

valueitraverseOf
  1. :: (Is k A_Traversal, Applicative f, HasSingleIndex is i)
  2. => Optic k is s t a b
  3. -> i -> a -> f b
  4. -> s
  5. -> f t
#

Map each element of a structure targeted by an IxTraversal (supplying the index), evaluate these actions from left to right, and collect the results.

This yields the van Laarhoven representation of an indexed traversal.

classclass (FunctorWithIndex i t, FoldableWithIndex i t, Traversable t) => TraversableWithIndex i (t :: Type -> Type) | t -> i where
#

A Traversable with an additional index.

An instance must satisfy a (modified) form of the Traversable laws:

itraverse (const Identity) ≡ Identity
fmap (itraverse f) . itraverse g ≡ getCompose . itraverse (\i -> Compose . fmap (f i) . g i)

Methods

Instances32TraversableWithIndex, …
typetype IxTraversalVL i s t a b = forall (f :: Type -> Type). Applicative f => (i -> a -> f b) -> s -> f t
#

Type synonym for a type-modifying van Laarhoven indexed traversal.

valueifailing
  1. :: (Is k A_Fold, Is l A_Fold, HasSingleIndex is1 i, HasSingleIndex is2 i)
  2. => Optic' k is1 s a
  3. -> Optic' l is2 s a
  4. -> IxFold i s a
#

Try the first IxFold. If it returns no entries, try the second one.

Example2 expressions
itoListOf (_1 % ifolded `ifailing` _2 % ifolded) (["a"], ["b","c"])[(0,"a")]itoListOf (_1 % ifolded `ifailing` _2 % ifolded) ([], ["b","c"])[(0,"b"),(1,"c")]
valueisets :: ((i -> a -> b) -> s -> t) -> IxSetter i s t a b
#

Build an indexed setter from a function to modify the element(s).

classclass Functor f => FunctorWithIndex i (f :: Type -> Type) | f -> i where
#

A Functor with an additional index.

Instances must satisfy a modified form of the Functor laws:

imap f . imap g ≡ imap (\i -> f i . g i)
imap (\_ a -> a) ≡ id

Methods

  • imap :: (i -> a -> b) -> f a -> f b

    Map with access to the index.

Instances34FunctorWithIndex, …
datadata A_Fold
#

Tag for a fold.

Instances30Is, ViewableOptic, JoinKinds, IxOptic, ToReadOnly, ReadOnlyOptic, …
valueifindMOf
  1. :: (Is k A_Fold, Monad m, HasSingleIndex is i)
  2. => Optic' k is s a
  3. -> i -> a -> m Bool
  4. -> s
  5. -> m (Maybe (i, a))
#

The ifindMOf function takes an IxFold, a monadic predicate that is also supplied the index, a structure and returns in the monad the left-most element of the structure matching the predicate, or Nothing if there is no such element.

When you don't need access to the index then findMOf is more flexible in what it accepts.

valueifindOf
  1. :: (Is k A_Fold, HasSingleIndex is i)
  2. => Optic' k is s a
  3. -> i -> a -> Bool
  4. -> s
  5. -> Maybe (i, a)
#

The ifindOf function takes an IxFold, a predicate that is also supplied the index, a structure and returns the left-most element of the structure along with its index matching the predicate, or Nothing if there is no such element.

When you don't need access to the index then findOf is more flexible in what it accepts.

valueifolding :: FoldableWithIndex i f => (s -> f a) -> IxFold i s a
#

Obtain an IxFold by lifting an operation that returns a FoldableWithIndex result.

This can be useful to lift operations from Data.List and elsewhere into an IxFold.

Example1 expression
itoListOf (ifolding words) "how are you"[(0,"how"),(1,"are"),(2,"you")]
valueifoldring
  1. :: forall (f :: Type -> Type). Applicative f => (i -> a -> f u -> f u) -> f v -> s -> f w
  2. -> IxFold i s a
#

Obtain an IxFold by lifting ifoldr like function.

Example1 expression
itoListOf (ifoldring ifoldr) "hello"[(0,'h'),(1,'e'),(2,'l'),(3,'l'),(4,'o')]
classclass Foldable f => FoldableWithIndex i (f :: Type -> Type) | f -> i where
#

A container that supports folding with an additional index.

Methods

  • ifoldMap :: Monoid m => (i -> a -> m) -> f a -> m

    Fold a container by mapping value to an arbitrary Monoid with access to the index i.

    When you don't need access to the index then foldMap is more flexible in what it accepts.

    foldMap ≡ ifoldMap . const
    
  • ifoldMap' :: Monoid m => (i -> a -> m) -> f a -> m

    A variant of ifoldMap that is strict in the accumulator.

    When you don't need access to the index then foldMap' is more flexible in what it accepts.

    foldMap' ≡ ifoldMap' . const
    
  • ifoldr :: (i -> a -> b -> b) -> b -> f a -> b

    Right-associative fold of an indexed container with access to the index i.

    When you don't need access to the index then foldr is more flexible in what it accepts.

    foldr ≡ ifoldr . const
    
  • ifoldl :: (i -> b -> a -> b) -> b -> f a -> b

    Left-associative fold of an indexed container with access to the index i.

    When you don't need access to the index then foldl is more flexible in what it accepts.

    foldl ≡ ifoldl . const
    
  • ifoldr' :: (i -> a -> b -> b) -> b -> f a -> b

    Strictly fold right over the elements of a structure with access to the index i.

    When you don't need access to the index then foldr' is more flexible in what it accepts.

    foldr' ≡ ifoldr' . const
    
  • ifoldl' :: (i -> b -> a -> b) -> b -> f a -> b

    Fold over the elements of a structure with an index, associating to the left, but strictly.

    When you don't need access to the index then foldlOf' is more flexible in what it accepts.

    foldl' l ≡ ifoldl' l . const
    
Instances32FoldableWithIndex, …
datadata An_AffineFold
#

Tag for an affine fold.

Instances29Is, ViewableOptic, JoinKinds, IxOptic, ToReadOnly, ReadOnlyOptic, …
valueanyOf :: Is k A_Fold => Optic' k is s a -> (a -> Bool) -> s -> Bool
#

Returns True if any target of a Fold satisfies a predicate.

Example1 expression
anyOf each (=='x') ('x','y')True
valuefindMOf
  1. :: (Is k A_Fold, Monad m)
  2. => Optic' k is s a
  3. -> a -> m Bool
  4. -> s
  5. -> m (Maybe a)
#

The findMOf function takes a Fold, a monadic predicate and a structure and returns in the monad the leftmost element of the structure matching the predicate, or Nothing if there is no such element.

Example1 expression
findMOf each (\x -> print ("Checking " ++ show x) >> return (even x)) (1,3,4,6)"Checking 1""Checking 3""Checking 4"Just 4
Example1 expression
findMOf each (\x -> print ("Checking " ++ show x) >> return (even x)) (1,3,5,7)"Checking 1""Checking 3""Checking 5""Checking 7"Nothing
findMOf folded :: (Monad m, Foldable f) => (a -> m Bool) -> f a -> m (Maybe a)
valuefindOf :: Is k A_Fold => Optic' k is s a -> (a -> Bool) -> s -> Maybe a
#

The findOf function takes a Fold, a predicate and a structure and returns the leftmost element of the structure matching the predicate, or Nothing if there is no such element.

Example1 expression
findOf each even (1,3,4,6)Just 4
Example1 expression
findOf folded even [1,3,5,7]Nothing
find ≡ findOf folded
valuenoneOf :: Is k A_Fold => Optic' k is s a -> (a -> Bool) -> s -> Bool
#

Returns True only if no targets of a Fold satisfy a predicate.

Example2 expressions
noneOf each (not . isn't _Nothing) (Just 3, Just 4, Just 5)TruenoneOf (folded % folded) (<10) [[13,99,20],[3,71,42]]False
valuepreview :: Is k An_AffineFold => Optic' k is s a -> s -> Maybe a
#

Retrieve the value targeted by an AffineFold.

Example1 expression
let _Right = prism Right $ either (Left . Left) Right
Example1 expression
preview _Right (Right 'x')Just 'x'
Example1 expression
preview _Right (Left 'y')Nothing
typetype IxAffineTraversalVL i s t a b = forall (f :: Type -> Type). Functor f => (forall r. r -> f r) -> (i -> a -> f b) -> s -> f t
#

Type synonym for a type-modifying van Laarhoven indexed affine traversal.

Note: this isn't exactly van Laarhoven representation as there is no Pointed class (which would be a superclass of Applicative that contains pure but not <*>). You can interpret the first argument as a dictionary of Pointed that supplies the point function (i.e. the implementation of pure).

valueafailing
  1. :: (Is k An_AffineFold, Is l An_AffineFold)
  2. => Optic' k is s a
  3. -> Optic' l js s a
  4. -> AffineFold s a
#

Try the first AffineFold. If it returns no entry, try the second one.

Example1 expression
preview (ix 1 % re _Left `afailing` ix 2 % re _Right) [0,1,2,3]Just (Left 1)
Example1 expression
preview (ix 42 % re _Left `afailing` ix 2 % re _Right) [0,1,2,3]Just (Right 2)
datadata A_Getter
#

Tag for a getter.

Instances31ReversibleOptic, Is, ViewableOptic, JoinKinds, IxOptic, ToReadOnly, …
valueito :: (s -> (i, a)) -> IxGetter i s a
#

Build an indexed getter from a function.

Example1 expression
iview (ito id) ('i', 'x')('i','x')
valuedevoid :: IxLens' i Void a
#

There is an indexed field for every type in the Void.

Example1 expression
set (mapped % devoid) 1 [][]
Example1 expression
over (_Just % devoid) abs NothingNothing
valueifst :: IxLens i (a, i) (b, i) a b
#

Indexed _1 with other half of a pair as an index.

See isnd for examples.

valueilens :: (s -> (i, a)) -> (s -> b -> t) -> IxLens i s t a b
#

Build an indexed lens from a getter and a setter.

If you want to build an IxLens from the van Laarhoven representation, use ilensVL.

valueisnd :: IxLens i (i, a) (i, b) a b
#

Indexed _2 with other half of a pair as an index. Specialized version of itraversed to pairs, which can be IxLens.

Example1 expression
iview isnd ('a', True)('a',True)

That is not possible with itraversed, because it is an IxTraversal.

Example1 expression
:t itraversed :: IxTraversal i (i, a) (i, b) a bitraversed :: IxTraversal i (i, a) (i, b) a b  :: IxTraversal i (i, a) (i, b) a b
typetype IxLensVL i s t a b = forall (f :: Type -> Type). Functor f => (i -> a -> f b) -> s -> f t
#

Type synonym for a type-modifying van Laarhoven indexed lens.

typetype IxLensVL' i s a = IxLensVL i s s a a
#

Type synonym for a type-preserving van Laarhoven indexed lens.

datadata An_Iso
#

Tag for an iso.

Instances44ReversibleOptic, Is, ArrowOptic, ViewableOptic, PermeableOptic, JoinKinds, …
valueanon :: a -> (a -> Bool) -> Iso' (Maybe a) a
#

anon a p generalizes non a to take any value and a predicate.

anon a ≡ non' . nearly a

This function assumes that p a holds True and generates an isomorphism between Maybe (a | not (p a)) and a.

Example1 expression
Map.empty & at "hello" % anon Map.empty Map.null % at "world" ?~ "!!!"fromList [("hello",fromList [("world","!!!")])]
Example1 expression
Map.fromList [("hello", Map.fromList [("world","!!!")])] & at "hello" % anon Map.empty Map.null % at "world" .~ NothingfromList []
valueau :: Functor f => Iso s t a b -> ((b -> t) -> f s) -> f a
#

Based on ala from Conor McBride's work on Epigram.

This version is generalized to accept any Iso, not just a newtype.

Example1 expression
au (coerced1 @Sum) foldMap [1,2,3,4]10

You may want to think of this combinator as having the following, simpler type:

au :: Iso s t a b -> ((b -> t) -> e -> s) -> e -> a
valuecoerced :: (Coercible s a, Coercible t b) => Iso s t a b
#

Data types that are representationally equal are isomorphic.

Example1 expression
view coerced 'x' :: Identity CharIdentity 'x'
valuecoerced1 :: (Coercible s (f s), Coercible a (f a)) => Iso (f s) (f a) s a
#

Special case of coerced for trivial newtype wrappers.

Example1 expression
over (coerced1 @Identity) (++ "bar") (Identity "foo")Identity "foobar"
valuecoercedTo :: Coercible s a => Iso' s a
#

Type-preserving version of coerced with type parameters rearranged for TypeApplications.

Example1 expression
newtype MkInt = MkInt Int deriving Show
Example1 expression
over (coercedTo @Int) (*3) (MkInt 2)MkInt 6
valuecurried :: Iso ((a, b) -> c) ((d, e) -> f) (a -> b -> c) (d -> e -> f)
#

The canonical isomorphism for currying and uncurrying a function.

curried = iso curry uncurry
Example1 expression
view curried fst 3 43
valueequality :: (s ~ a, t ~ b) => Iso s t a b
#

Capture type constraints as an isomorphism.

Note: This is the identity optic:

Example1 expression
:t view equalityview equality :: a -> a
valueflipped :: Iso (a -> b -> c) (a' -> b' -> c') (b -> a -> c) (b' -> a' -> c')
#

The isomorphism for flipping a function.

Example1 expression
(view flipped (,)) 1 2(2,1)
valueinvoluted :: (a -> a) -> Iso' a a
#

Given a function that is its own inverse, this gives you an Iso using it in both directions.

involuted ≡ join iso
Example1 expression
"live" ^. involuted reverse"evil"
Example1 expression
"live" & involuted reverse %~ ('d':)"lived"
valueiso :: (s -> a) -> (b -> t) -> Iso s t a b
#

Build an iso from a pair of inverse functions.

If you want to build an Iso from the van Laarhoven representation, use isoVL from the optics-vl package.

valuenon :: Eq a => a -> Iso' (Maybe a) a
#

If v is an element of a type a, and a' is a sans the element v, then non v is an isomorphism from Maybe a' to a.

non ≡ non' . only

Keep in mind this is only a real isomorphism if you treat the domain as being Maybe (a sans v).

This is practically quite useful when you want to have a Data.Map.Map where all the entries should have non-zero values.

Example1 expression
Map.fromList [("hello",1)] & at "hello" % non 0 %~ (+2)fromList [("hello",3)]
Example1 expression
Map.fromList [("hello",1)] & at "hello" % non 0 %~ (subtract 1)fromList []
Example1 expression
Map.fromList [("hello",1)] ^. at "hello" % non 01
Example1 expression
Map.fromList [] ^. at "hello" % non 00

This combinator is also particularly useful when working with nested maps.

e.g. When you want to create the nested Data.Map.Map when it is missing:

Example1 expression
Map.empty & at "hello" % non Map.empty % at "world" ?~ "!!!"fromList [("hello",fromList [("world","!!!")])]

and when have deleting the last entry from the nested Data.Map.Map mean that we should delete its entry from the surrounding one:

Example1 expression
Map.fromList [("hello", Map.fromList [("world","!!!")])] & at "hello" % non Map.empty % at "world" .~ NothingfromList []

It can also be used in reverse to exclude a given value:

Example1 expression
non 0 # rem 10 4Just 2
Example1 expression
non 0 # rem 10 5Nothing
valuenon' :: Prism' a () -> Iso' (Maybe a) a
#

non' p generalizes non (p # ()) to take any unit Prism

This function generates an isomorphism between Maybe (a | isn't p a) and a.

Example1 expression
Map.singleton "hello" Map.empty & at "hello" % non' _Empty % at "world" ?~ "!!!"fromList [("hello",fromList [("world","!!!")])]
Example1 expression
Map.fromList [("hello", Map.fromList [("world","!!!")])] & at "hello" % non' _Empty % at "world" .~ NothingfromList []
valuewithIso :: Iso s t a b -> ((s -> a) -> (b -> t) -> r) -> r
#

Extract the two components of an isomorphism.

valueto :: (s -> a) -> Getter s a
#

Build a getter from a function.

valueview :: Is k A_Getter => Optic' k is s a -> s -> a
#

View the value pointed to by a getter.

If you want to view a type-modifying optic that is insufficiently polymorphic to be type-preserving, use getting.

valueviews :: Is k A_Getter => Optic' k is s a -> (a -> r) -> s -> r
#

View the function of the value pointed to by a getter.

valueasumOf :: (Is k A_Fold, Alternative f) => Optic' k is s (f a) -> s -> f a
#

The sum of a collection of actions.

Example1 expression
asumOf each ("hello","world")"helloworld"
Example1 expression
asumOf each (Nothing, Just "hello", Nothing)Just "hello"
asum ≡ asumOf folded
valuecosmosOf :: Is k A_Fold => Optic' k is a a -> Fold a a
#

Given a Fold that knows how to locate immediate children, fold all of the transitive descendants of a node, including itself.

valuefolding :: Foldable f => (s -> f a) -> Fold s a
#

Obtain a Fold by lifting an operation that returns a Foldable result.

This can be useful to lift operations from Data.List and elsewhere into a Fold.

Example1 expression
toListOf (folding tail) [1,2,3,4][2,3,4]
valuefoldlOf' :: Is k A_Fold => Optic' k is s a -> (r -> a -> r) -> r -> s -> r
#

Fold left-associatively, and strictly.

valuefoldring
  1. :: forall (f :: Type -> Type). Applicative f => (a -> f u -> f u) -> f v -> s -> f w
  2. -> Fold s a
#

Obtain a Fold by lifting foldr like function.

Example1 expression
toListOf (foldring foldr) [1,2,3,4][1,2,3,4]
valuehas :: Is k A_Fold => Optic' k is s a -> s -> Bool
#

Check to see if this optic matches 1 or more entries.

Example1 expression
has _Left (Left 12)True
Example1 expression
has _Right (Left 12)False

This will always return True for a Lens or Getter.

Example1 expression
has _1 ("hello","world")True
valuehasn't :: Is k A_Fold => Optic' k is s a -> s -> Bool
#

Check to see if this Fold or Traversal has no matches.

Example1 expression
hasn't _Left (Right 12)True
Example1 expression
hasn't _Left (Left 12)False
valuelastOf :: Is k A_Fold => Optic' k is s a -> s -> Maybe a
#

Retrieve the last entry of a Fold.

Example1 expression
lastOf folded [1..10]Just 10
Example1 expression
lastOf each (1,2)Just 2
valuelengthOf :: Is k A_Fold => Optic' k is s a -> s -> Int
#

Calculate the number of targets there are for a Fold in a given container.

Note: This can be rather inefficient for large containers and just like length, this will not terminate for infinite folds.

length ≡ lengthOf folded
Example1 expression
lengthOf _1 ("hello",())1
Example1 expression
lengthOf folded [1..10]10
Example1 expression
lengthOf (folded % folded) [[1,2],[3,4],[5,6]]6
valuelookupOf :: (Is k A_Fold, Eq a) => Optic' k is s (a, v) -> a -> s -> Maybe v
#

The lookupOf function takes a Fold, a key, and a structure containing key/value pairs. It returns the first value corresponding to the given key. This function generalizes lookup to work on an arbitrary Fold instead of lists.

Example1 expression
lookupOf folded 4 [(2, 'a'), (4, 'b'), (4, 'c')]Just 'b'
Example1 expression
lookupOf folded 2 [(2, 'a'), (4, 'b'), (4, 'c')]Just 'a'
valuemaximumOf :: (Is k A_Fold, Ord a) => Optic' k is s a -> s -> Maybe a
#

Obtain the maximum element (if any) targeted by a Fold safely.

Note: maximumOf on a valid Iso, Lens or Getter will always return Just a value.

Example1 expression
maximumOf folded [1..10]Just 10
Example1 expression
maximumOf folded []Nothing
Example1 expression
maximumOf (folded % filtered even) [1,4,3,6,7,9,2]Just 6
maximum ≡ fromMaybe (error "empty") . maximumOf folded

In the interest of efficiency, This operation has semantics more strict than strictly necessary. \o -> getMax . foldMapOf o Max has lazier semantics but could leak memory.

valueminimumOf :: (Is k A_Fold, Ord a) => Optic' k is s a -> s -> Maybe a
#

Obtain the minimum element (if any) targeted by a Fold safely.

Note: minimumOf on a valid Iso, Lens or Getter will always return Just a value.

Example1 expression
minimumOf folded [1..10]Just 1
Example1 expression
minimumOf folded []Nothing
Example1 expression
minimumOf (folded % filtered even) [1,4,3,6,7,9,2]Just 2
minimum ≡ fromMaybe (error "empty") . minimumOf folded

In the interest of efficiency, This operation has semantics more strict than strictly necessary. \o -> getMin . foldMapOf o Min has lazier semantics but could leak memory.

valuemsumOf :: (Is k A_Fold, MonadPlus m) => Optic' k is s (m a) -> s -> m a
#

The sum of a collection of actions.

Example1 expression
msumOf each ("hello","world")"helloworld"
Example1 expression
msumOf each (Nothing, Just "hello", Nothing)Just "hello"
msum ≡ msumOf folded
valuenotElemOf :: (Is k A_Fold, Eq a) => Optic' k is s a -> a -> s -> Bool
#

Does the element not occur anywhere within a given Fold of the structure?

Example1 expression
notElemOf each 'd' ('a','b','c')True
Example1 expression
notElemOf each 'a' ('a','b','c')False
notElem ≡ notElemOf folded
valueparaOf :: Is k A_Fold => Optic' k is a a -> (a -> [r] -> r) -> a -> r
#

Perform a fold-like computation on each value, technically a paramorphism.

valuesumOf :: (Is k A_Fold, Num a) => Optic' k is s a -> s -> a
#

Calculate the Sum of every number targeted by a Fold.

Example3 expressions
sumOf each (5,6)11sumOf folded [1,2,3,4]10sumOf (folded % each) [(1,2),(3,4)]10
sum ≡ sumOf folded

This operation may be more strict than you would expect. If you want a lazier version use \o -> getSum . foldMapOf o Sum

valueunfolded :: (s -> Maybe (a, s)) -> Fold s a
#

Build a Fold that unfolds its values from a seed.

Prelude.unfoldr ≡ toListOf . unfolded
Example1 expression
toListOf (unfolded $ \b -> if b == 0 then Nothing else Just (b, b - 1)) 10[10,9,8,7,6,5,4,3,2,1]
valueuniverseOf :: Is k A_Fold => Optic' k is a a -> a -> [a]
#

Given a Fold that knows how to locate immediate children, retrieve all of the transitive descendants of a node, including itself.

valueunsafeFiltered :: (a -> Bool) -> AffineTraversal' a a
#

Filter result(s) of a traversal that don't satisfy a predicate.

Note: This is not a legal Traversal, unless you are very careful not to invalidate the predicate on the target.

As a counter example, consider that given evens = unsafeFiltered even the second Traversal law is violated:

over evens succ . over evens succ /= over evens (succ . succ)

So, in order for this to qualify as a legal Traversal you can only use it for actions that preserve the result of the predicate!

For a safe variant see indices (or filtered for read-only optics).

typetype AffineTraversalVL s t a b = forall (f :: Type -> Type). Functor f => (forall r. r -> f r) -> (a -> f b) -> s -> f t
#

Type synonym for a type-modifying van Laarhoven affine traversal.

Note: this isn't exactly van Laarhoven representation as there is no Pointed class (which would be a superclass of Applicative that contains pure but not <*>). You can interpret the first argument as a dictionary of Pointed that supplies the point function (i.e. the implementation of pure).

A TraversalVL has Applicative available and hence can combine the effects arising from multiple elements using <*>. In contrast, an AffineTraversalVL has no way to combine effects from multiple elements, so it must act on at most one element. (It can act on none at all thanks to the availability of point.)

Optic operators

value(?~) :: Is k A_Setter => Optic k is s t a (Maybe b) -> b -> s -> t
#

Set the target of a Setter to Just a value.

o ?~ b ≡ set o (Just b)
Example1 expression
Nothing & equality ?~ 'x'Just 'x'
Example1 expression
Map.empty & at 3 ?~ 'x'fromList [(3,'x')]

Optics utilities

0 declarations

At

An AffineTraversal to traverse a key in a map or an element of a sequence:

Example1 expression
preview (ix 1) ['a','b','c']Just 'b'

a Lens to get, set or delete a key in a map:

Example1 expression
set (at 0) (Just 'b') (Map.fromList [(0, 'a')])fromList [(0,'b')]

and a Lens to insert or remove an element of a set:

Example1 expression
IntSet.fromList [1,2,3,4] & contains 3 .~ FalsefromList [1,2,4]
classclass (Ixed m, IxKind m ~ An_AffineTraversal) => At m where
#

At provides a Lens that can be used to read, write or delete the value associated with a key in a Map-like container on an ad hoc basis.

An instance of At should satisfy:

ix k ≡ at k % _Just

Methods

  • at :: Index m -> Lens' m (Maybe (IxValue m))
    Example1 expression
    Map.fromList [(1,"world")] ^. at 1Just "world"
    Example1 expression
    at 1 ?~ "hello" $ Map.emptyfromList [(1,"hello")]

    Note: Usage of this function might introduce space leaks if you're not careful to make sure that values put inside the Just constructor are evaluated. To force the values and avoid such leaks, use at' instead.

    Note: Map-like containers form a reasonable instance, but not Array-like ones, where you cannot satisfy the Lens laws.

Instances7At, …
  • At IntSetDefined in optics-core-0.4.1.1 · Optics.At.Core
  • Ord k => At (Set k)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • At (IntMap a)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • At (Maybe a)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • (Eq k, Hashable k) => At (HashSet k)Defined in optics-extra-0.4.2.1 · Optics.At · orphan
  • Ord k => At (Map k a)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • (Eq k, Hashable k) => At (HashMap k a)Defined in optics-extra-0.4.2.1 · Optics.At · orphan
valueat' :: At m => Index m -> Lens' m (Maybe (IxValue m))
#

Version of at strict in the value inside the Just constructor.

Example:

Example1 expression
(at () .~ Just (error "oops") $ Nothing) `seq` ()()
Example1 expression
(at' () .~ Just (error "oops") $ Nothing) `seq` ()*** Exception: oops...
Example1 expression
view (at ()) (Just $ error "oops") `seq` ()()
Example1 expression
view (at' ()) (Just $ error "oops") `seq` ()*** Exception: oops...

It also works as expected for other data structures:

Example1 expression
(at 1 .~ Just (error "oops") $ Map.empty) `seq` ()()
Example1 expression
(at' 1 .~ Just (error "oops") $ Map.empty) `seq` ()*** Exception: oops...
valuesans :: At m => Index m -> m -> m
#

Delete the value associated with a key in a Map-like container

sans k = at k .~ Nothing
classclass Contains m where
#

This class provides a simple Lens that lets you view (and modify) information about whether or not a container contains a given Index. Instances are provided for Set-like containers only.

Methods

  • contains :: Index m -> Lens' m Bool
    Example1 expression
    IntSet.fromList [1,2,3,4] ^. contains 3True
    Example1 expression
    IntSet.fromList [1,2,3,4] ^. contains 5False
    Example1 expression
    IntSet.fromList [1,2,3,4] & contains 3 .~ FalsefromList [1,2,4]
Instances3Contains
familytype family Index s
#

Type family that takes a key-value container type and returns the type of keys (indices) into the container, for example Index (Map k a) ~ k. This is shared by Ixed, At and Contains.

Instances32Index, …
  • type Index ByteString = IntDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type Index ByteString = Int64Defined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type Index IntSet = IntDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index Text = IntDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type Index Text = Int64Defined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type Index (UArray i e) = iDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (Complex a) = IntDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (IntMap a) = IntDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (Map k a) = kDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (Seq a) = IntDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (Set a) = aDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (Tree a) = [Int]Defined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (Array i e) = iDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (NonEmpty a) = IntDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (Identity a) = ()Defined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (Maybe a) = ()Defined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (HashMap k a) = kDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type Index (HashSet a) = aDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type Index (Vector a) = IntDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type Index (Vector a) = IntDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type Index (Vector a) = IntDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type Index (Vector a) = IntDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type Index (a, b) = IntDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (a, b, c) = IntDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (a, b, c, d) = IntDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (a, b, c, d, e) = IntDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (a, b, c, d, e, f) = IntDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (a, b, c, d, e, f, g) = IntDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (a, b, c, d, e, f, g, h) = IntDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (a, b, c, d, e, f, g, h, i) = IntDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index (e -> a) = eDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type Index [a] = IntDefined in optics-core-0.4.1.1 · Optics.At.Core
familytype family IxValue m
#

Type family that takes a key-value container type and returns the type of values stored in the container, for example IxValue (Map k a) ~ a. This is shared by both Ixed and At.

Instances31IxValue, …
  • type IxValue ByteString = Word8Defined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type IxValue ByteString = Word8Defined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type IxValue IntSet = ()Defined in optics-core-0.4.1.1 · Optics.At.Core
  • type IxValue Text = CharDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type IxValue Text = CharDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type IxValue (UArray i e) = eDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type IxValue (IntMap a) = aDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type IxValue (Map k a) = aDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type IxValue (Seq a) = aDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type IxValue (Set k) = ()Defined in optics-core-0.4.1.1 · Optics.At.Core
  • type IxValue (Tree a) = aDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type IxValue (Array i e) = eDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type IxValue (NonEmpty a) = aDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type IxValue (Identity a) = aDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type IxValue (Maybe a) = aDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type IxValue (HashMap k a) = aDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type IxValue (HashSet k) = ()Defined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type IxValue (Vector a) = aDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type IxValue (Vector a) = aDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type IxValue (Vector a) = aDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type IxValue (Vector a) = aDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • type IxValue (a0, a1, a2) = a0Defined in optics-core-0.4.1.1 · Optics.At.Core
    ix :: Int -> AffineTraversal' (a, a, a) a
  • type IxValue (a0, a1, a2, a3) = a0Defined in optics-core-0.4.1.1 · Optics.At.Core
    ix :: Int -> AffineTraversal' (a, a, a, a) a
  • type IxValue (a0, a1, a2, a3, a4) = a0Defined in optics-core-0.4.1.1 · Optics.At.Core
    ix :: Int -> AffineTraversal' (a, a, a, a, a) a
  • type IxValue (a0, a1, a2, a3, a4, a5) = a0Defined in optics-core-0.4.1.1 · Optics.At.Core
    ix :: Int -> AffineTraversal' (a, a, a, a, a, a) a
  • type IxValue (a0, a1, a2, a3, a4, a5, a6) = a0Defined in optics-core-0.4.1.1 · Optics.At.Core
    ix :: Int -> AffineTraversal' (a, a, a, a, a, a, a) a
  • type IxValue (a0, a1, a2, a3, a4, a5, a6, a7) = a0Defined in optics-core-0.4.1.1 · Optics.At.Core
    ix :: Int -> AffineTraversal' (a, a, a, a, a, a, a, a) a
  • type IxValue (a0, a1, a2, a3, a4, a5, a6, a7, a8) = a0Defined in optics-core-0.4.1.1 · Optics.At.Core
    ix :: Int -> AffineTraversal' (a, a, a, a, a, a, a, a, a) a
  • type IxValue (a0, a2) = a0Defined in optics-core-0.4.1.1 · Optics.At.Core
    ix :: Int -> AffineTraversal' (a, a) a
  • type IxValue (e -> a) = aDefined in optics-core-0.4.1.1 · Optics.At.Core
  • type IxValue [a] = aDefined in optics-core-0.4.1.1 · Optics.At.Core
classclass Ixed m where
#

Provides a simple AffineTraversal lets you traverse the value at a given key in a Map or element at an ordinal position in a list or Seq.

Associated types

  • type family IxKind m :: OpticKind

    Type family that takes a key-value container type and returns the kind of optic to index into it. For most containers, it's An_AffineTraversal, Representable (Naperian) containers it is A_Lens, and multi-maps would have A_Traversal.

Methods

  • ix :: Index m -> Optic' (IxKind m) NoIx m (IxValue m)

    NB: Setting the value of this AffineTraversal will only set the value in at if it is already present.

    If you want to be able to insert missing values, you want at.

    Example1 expression
    [1,2,3,4] & ix 2 %~ (*10)[1,2,30,4]
    Example1 expression
    "abcd" & ix 2 .~ 'e'"abed"
    Example1 expression
    "abcd" ^? ix 2Just 'c'
    Example1 expression
    [] ^? ix 2Nothing
Instances31Ixed, …
  • Ixed ByteStringDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • Ixed ByteStringDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • Ixed IntSetDefined in optics-core-0.4.1.1 · Optics.At.Core
  • Ixed TextDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • Ixed TextDefined in optics-extra-0.4.2.1 · Optics.At · orphan
  • Storable a => Ixed (Vector a)Defined in optics-extra-0.4.2.1 · Optics.At · orphan
  • Ord k => Ixed (Set k)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • Ixed (IntMap a)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • Ixed (Seq a)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • Ixed (Tree a)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • Ixed (NonEmpty a)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • Ixed (Identity a)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • Ixed (Maybe a)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • Ixed (Vector a)Defined in optics-extra-0.4.2.1 · Optics.At · orphan
  • Ixed [a]Defined in optics-core-0.4.1.1 · Optics.At.Core
  • Prim a => Ixed (Vector a)Defined in optics-extra-0.4.2.1 · Optics.At · orphan
  • Unbox a => Ixed (Vector a)Defined in optics-extra-0.4.2.1 · Optics.At · orphan
  • (Eq k, Hashable k) => Ixed (HashSet k)Defined in optics-extra-0.4.2.1 · Optics.At · orphan
  • Ix i => Ixed (Array i e)Defined in optics-core-0.4.1.1 · Optics.At.Core
    arr ! i ≡ arr ^. ix i
    arr // [(i,e)] ≡ ix i .~ e $ arr
    
  • Eq e => Ixed (e -> a)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • Ord k => Ixed (Map k a)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • (IArray UArray e, Ix i) => Ixed (UArray i e)Defined in optics-core-0.4.1.1 · Optics.At.Core
    arr ! i ≡ arr ^. ix i
    arr // [(i,e)] ≡ ix i .~ e $ arr
    
  • (Eq k, Hashable k) => Ixed (HashMap k a)Defined in optics-extra-0.4.2.1 · Optics.At · orphan
  • a0 ~ a1 => Ixed (a0, a1)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • (a0 ~ a1, a0 ~ a2) => Ixed (a0, a1, a2)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • (a0 ~ a1, a0 ~ a2, a0 ~ a3) => Ixed (a0, a1, a2, a3)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • (a0 ~ a1, a0 ~ a2, a0 ~ a3, a0 ~ a4) => Ixed (a0, a1, a2, a3, a4)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • (a0 ~ a1, a0 ~ a2, a0 ~ a3, a0 ~ a4, a0 ~ a5) => Ixed (a0, a1, a2, a3, a4, a5)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • (a0 ~ a1, a0 ~ a2, a0 ~ a3, a0 ~ a4, a0 ~ a5, a0 ~ a6) => Ixed (a0, a1, a2, a3, a4, a5, a6)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • (a0 ~ a1, a0 ~ a2, a0 ~ a3, a0 ~ a4, a0 ~ a5, a0 ~ a6, a0 ~ a7) => Ixed (a0, a1, a2, a3, a4, a5, a6, a7)Defined in optics-core-0.4.1.1 · Optics.At.Core
  • (a0 ~ a1, a0 ~ a2, a0 ~ a3, a0 ~ a4, a0 ~ a5, a0 ~ a6, a0 ~ a7, a0 ~ a8) => Ixed (a0, a1, a2, a3, a4, a5, a6, a7, a8)Defined in optics-core-0.4.1.1 · Optics.At.Core
familytype family IxKind m :: OpticKind
#

Type family that takes a key-value container type and returns the kind of optic to index into it. For most containers, it's An_AffineTraversal, Representable (Naperian) containers it is A_Lens, and multi-maps would have A_Traversal.

Instances31IxKind, …

Cons

Prisms to match on the left or right side of a list, vector or other sequential structure:

Example1 expression
preview _Cons "abc"Just ('a',"bc")
Example1 expression
preview _Snoc "abc"Just ("ab",'c')
classclass Cons s t a b | s -> a, t -> b, s b -> t, t a -> s where
#

This class provides a way to attach or detach elements on the left side of a structure in a flexible manner.

Methods

Instances11Cons, …
valueuncons :: Cons s s a a => s -> Maybe (a, s)
#

Attempt to extract the left-most element from a container, and a version of the container without that element.

Example1 expression
uncons []Nothing
Example1 expression
uncons [1, 2, 3]Just (1,[2,3])
valuecons :: Cons s s a a => a -> s -> s
#

cons an element onto a container.

Example1 expression
cons 'a' """a"
Example1 expression
cons 'a' "bc""abc"
patternpattern (:<) :: Cons s s a a => a -> s -> s
#

Pattern synonym for matching on the leftmost element of a structure.

Example1 expression
case ['a','b','c'] of (x :< _) -> x'a'
patternpattern (:>) :: Snoc s s a a => s -> a -> s
#

Pattern synonym for matching on the rightmost element of a structure.

Example1 expression
case ['a','b','c'] of (_ :> x) -> x'c'
value(<|) :: Cons s s a a => a -> s -> s
#

cons an element onto a container.

This is an infix alias for cons.

Example1 expression
1 <| [][1]
Example1 expression
'a' <| "bc""abc"
Example1 expression
1 <| [][1]
Example1 expression
1 <| [2, 3][1,2,3]
value_head :: Cons s s a a => AffineTraversal' s a
#

An AffineTraversal reading and writing to the head of a non-empty container.

Example1 expression
"abc" ^? _headJust 'a'
Example1 expression
"abc" & _head .~ 'd'"dbc"
Example1 expression
[1,2,3] & _head %~ (*10)[10,2,3]
Example1 expression
[] & _head %~ absurd[]
Example1 expression
[1,2,3] ^? _headJust 1
Example1 expression
[] ^? _headNothing
Example1 expression
[1,2] ^? _headJust 1
Example1 expression
[] & _head .~ 1[]
Example1 expression
[0] & _head .~ 2[2]
Example1 expression
[0,1] & _head .~ 2[2,1]
value_init :: Snoc s s a a => AffineTraversal' s s
#

An AffineTraversal reading and replacing all but the a last element of a non-empty container.

Example1 expression
"abcd" ^? _initJust "abc"
Example1 expression
"" ^? _initNothing
Example1 expression
"ab" & _init .~ "cde""cdeb"
Example1 expression
[] & _init .~ [1,2][]
Example1 expression
[1,2,3,4] & _init % traversed %~ (*10)[10,20,30,4]
Example1 expression
[1,2,3] ^? _initJust [1,2]
Example1 expression
"hello" ^? _initJust "hell"
Example1 expression
[] ^? _initNothing
value_last :: Snoc s s a a => AffineTraversal' s a
#

An AffineTraversal reading and writing to the last element of a non-empty container.

Example1 expression
"abc" ^? _lastJust 'c'
Example1 expression
"" ^? _lastNothing
Example1 expression
[1,2,3] & _last %~ (+1)[1,2,4]
Example1 expression
[1,2] ^? _lastJust 2
Example1 expression
[] & _last .~ 1[]
Example1 expression
[0] & _last .~ 2[2]
Example1 expression
[0,1] & _last .~ 2[0,2]
value_tail :: Cons s s a a => AffineTraversal' s s
#

An AffineTraversal reading and writing to the tail of a non-empty container.

Example1 expression
"ab" & _tail .~ "cde""acde"
Example1 expression
[] & _tail .~ [1,2][]
Example1 expression
[1,2,3,4,5] & _tail % traversed %~ (*10)[1,20,30,40,50]
Example1 expression
[1,2] & _tail .~ [3,4,5][1,3,4,5]
Example1 expression
[] & _tail .~ [1,2][]
Example1 expression
"abc" ^? _tailJust "bc"
Example1 expression
"hello" ^? _tailJust "ello"
Example1 expression
"" ^? _tailNothing
valuesnoc :: Snoc s s a a => s -> a -> s
#

snoc an element onto the end of a container.

Example1 expression
snoc "hello" '!'"hello!"
valueunsnoc :: Snoc s s a a => s -> Maybe (s, a)
#

Attempt to extract the right-most element from a container, and a version of the container without that element.

Example1 expression
unsnoc "hello!"Just ("hello",'!')
Example1 expression
unsnoc ""Nothing
value(|>) :: Snoc s s a a => s -> a -> s
#

snoc an element onto the end of a container.

This is an infix alias for snoc.

Example1 expression
"" |> 'a'"a"
Example1 expression
"bc" |> 'a'"bca"
classclass Snoc s t a b | s -> a, t -> b, s b -> t, t a -> s where
#

This class provides a way to attach or detach elements on the right side of a structure in a flexible manner.

Methods

Instances11Snoc, …

Each

An IxTraversal for each element of a (potentially monomorphic) container.

Example1 expression
over each (*10) (1,2,3)(10,20,30)
classclass Each i s t a b | s -> i a, t -> i b, s b -> t, t a -> s where
#

Extract each element of a (potentially monomorphic) container.

Example1 expression
over each (*10) (1,2,3)(10,20,30)
Example1 expression
iover each (\i a -> a*10 + succ i) (1,2,3)(11,22,33)

Methods

Instances29Each, …

Empty

A Prism for a container type that may be empty.

Example1 expression
isn't _Empty [1,2,3]True
patternpattern Empty :: AsEmpty a => a
#

Pattern synonym for matching on any type with an AsEmpty instance.

Example1 expression
case Nothing of { Empty -> True; _ -> False }True
classclass AsEmpty a where
#

Class for types that may be _Empty.

Methods

  • _Empty :: Prism' a ()
    Example1 expression
    isn't _Empty [1,2,3]True
Instances29AsEmpty, …
  • AsEmpty ByteStringDefined in optics-extra-0.4.2.1 · Optics.Empty · orphan
  • AsEmpty ByteStringDefined in optics-extra-0.4.2.1 · Optics.Empty · orphan
  • AsEmpty IntSetDefined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty AllDefined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty AnyDefined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty EventDefined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty OrderingDefined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty TextDefined in optics-extra-0.4.2.1 · Optics.Empty · orphan
  • AsEmpty TextDefined in optics-extra-0.4.2.1 · Optics.Empty · orphan
  • AsEmpty ()Defined in optics-core-0.4.1.1 · Optics.Empty.Core
  • Storable a => AsEmpty (Vector a)Defined in optics-extra-0.4.2.1 · Optics.Empty · orphan
  • AsEmpty (IntMap a)Defined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty (Seq a)Defined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty (Set a)Defined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty (First a)Defined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty (Last a)Defined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty (ZipList a)Defined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty (Maybe a)Defined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty (HashSet a)Defined in optics-extra-0.4.2.1 · Optics.Empty · orphan
  • AsEmpty (Vector a)Defined in optics-extra-0.4.2.1 · Optics.Empty · orphan
  • AsEmpty [a]Defined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty a => AsEmpty (Dual a)Defined in optics-core-0.4.1.1 · Optics.Empty.Core
  • Unbox a => AsEmpty (Vector a)Defined in optics-extra-0.4.2.1 · Optics.Empty · orphan
  • (Eq a, Num a) => AsEmpty (Product a)Defined in optics-core-0.4.1.1 · Optics.Empty.Core
  • (Eq a, Num a) => AsEmpty (Sum a)Defined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty (Map k a)Defined in optics-core-0.4.1.1 · Optics.Empty.Core
  • AsEmpty (HashMap k a)Defined in optics-extra-0.4.2.1 · Optics.Empty · orphan
  • (AsEmpty a, AsEmpty b) => AsEmpty (a, b)Defined in optics-core-0.4.1.1 · Optics.Empty.Core
  • (AsEmpty a, AsEmpty b, AsEmpty c) => AsEmpty (a, b, c)Defined in optics-core-0.4.1.1 · Optics.Empty.Core

Generic data access

classclass GAffineField (name :: Symbol) s t a b | name s -> t a b, name t -> s a b where
#

Focus on a possibly partial field name of type a within a type s using its Generic instance.

Example1 expression
:{data Fish = Herring { name :: String }          | Tuna    { name :: String, sleeping :: Bool }  deriving Generic:}
Example2 expressions
let herring = Herring { name = "Henry" }let tuna    = Tuna { name = "Tony", sleeping = True }
Example1 expression
herring ^? gafield @"name"Just "Henry"
Example1 expression
herring ^? gafield @"sleeping"Nothing
Example1 expression
tuna ^? gafield @"sleeping"Just True

Types without a Generic instance are not supported:

Example1 expression
NoG 'x' ^? gafield @"any"......Type ‘NoG’ doesn't have a Generic instance...In the......

Note: trying to access a field that doesn't exist in any data constructor results in an error:

Example1 expression
tuna ^? gafield @"salary"......Type ‘Fish’ doesn't have a field named ‘salary’...In the......

Methods

Instances2GAffineField
  • GAFieldContext repDefined name s t a b => GAffineField name s t a bDefined in optics-core-0.4.1.1 · Optics.Generic
  • (a ~ Void0, b ~ Void0) => GAffineField name Void0 Void0 a bDefined in optics-core-0.4.1.1 · Optics.Generic

    Hidden instance.

classclass GConstructor (name :: Symbol) s t a b | name s -> t a b, name t -> s a b where
#

Focus on a constructor name of a type s using its Generic instance.

Example1 expression
:{data Animal = Dog { name :: String, age :: Int }            | Cat { name :: String, purrs :: Bool }  deriving (Show, Generic):}
Example2 expressions
let dog = Dog "Sparky" 2let cat = Cat "Cuddly" True
Example1 expression
dog ^? gconstructor @"Dog"Just ("Sparky",2)
Example1 expression
dog ^? gconstructor @"Cat"Nothing
Example1 expression
cat & gconstructor @"Cat" % _2 %~ notCat {name = "Cuddly", purrs = False}
Example1 expression
dog & gconstructor @"Cat" % _1 .~ "Merry"Dog {name = "Sparky", age = 2}
Example1 expression
cat ^? gconstructor @"Parrot"......Type ‘Animal’ doesn't have a constructor named ‘Parrot’...In the......

Types without a Generic instance are not supported:

Example1 expression
NoG 'x' ^. gconstructor @"NoG"......Type ‘NoG’ doesn't have a Generic instance...In the......

Note: gconstructor is supported by labelOptic and can be used with a concise syntax via OverloadedLabels.

Example1 expression
dog ^? #_DogJust ("Sparky",2)
Example1 expression
cat & #_Cat % _1 .~ "Merry"Cat {name = "Merry", purrs = True}

Methods

Instances2GConstructor
  • GConstructorContext repDefined name s t a b => GConstructor name s t a bDefined in optics-core-0.4.1.1 · Optics.Generic
  • (a ~ Void0, b ~ Void0) => GConstructor name Void0 Void0 a bDefined in optics-core-0.4.1.1 · Optics.Generic

    Hidden instance.

classclass GField (name :: Symbol) s t a b | name s -> t a b, name t -> s a b where
#

Focus on a field name of type a within a type s using its Generic instance.

Example1 expression
:{data User a  = User { name :: String         , age  :: a         }  | LazyUser { name :: String             , age  :: a             , lazy :: Bool             }  deriving (Show, Generic):}
Example1 expression
let user = User "Tom" 32 :: User Int
Example1 expression
user ^. gfield @"name""Tom"
Example1 expression
user ^. gfield @"age"32
Example1 expression
user ^. gfield @"salary"......Data constructor ‘User’ doesn't have a field named ‘salary’...In the......

Only total fields are accessible (for partial ones see gafield):

Example1 expression
user ^. gfield @"lazy"......Data constructor ‘User’ doesn't have a field named ‘lazy’...In the......

Type changing updates are supported:

Example1 expression
user & gfield @"age" .~ ()User {name = "Tom", age = ()}

Types without a Generic instance are not supported:

Example1 expression
NoG 'x' ^. gfield @"any"......Type ‘NoG’ doesn't have a Generic instance...In the......

Note: gfield is supported by labelOptic and can be used with a concise syntax via OverloadedLabels.

Example1 expression
user ^. #name"Tom"
Example1 expression
user & #age %~ (+1)User {name = "Tom", age = 33}

Methods

Instances2GField
  • GFieldContext name s t a b => GField name s t a bDefined in optics-core-0.4.1.1 · Optics.Generic
  • (a ~ Void0, b ~ Void0) => GField name Void0 Void0 a bDefined in optics-core-0.4.1.1 · Optics.Generic

    Hidden instance.

classclass GPlate a s where
#

Traverse occurrences of a type a within a type s using its Generic instance.

Example1 expression
toListOf (gplate @Char) ('h', ((), 'e', Just 'l'), "lo")"hello"

If a occurs recursively in its own definition, only outermost occurrences of a within s will be traversed:

Example1 expression
toListOf (gplate @String) ("one","two")["one","two"]

Note: types without a Generic instance in scope when GPlate class constraint is resolved will not be entered during the traversal.

Example1 expression
let noG = (NoG 'n', (Just 'i', "c"), 'e')
Example1 expression
toListOf (gplate @Char) noG"ice"
Example1 expression
deriving instance Generic NoG
Example1 expression
toListOf (gplate @Char) noG"nice"

Methods

Instances3GPlate
  • GPlate Void0 aDefined in optics-core-0.4.1.1 · Optics.Generic

    Hidden instance.

  • GPlate a Void0Defined in optics-core-0.4.1.1 · Optics.Generic

    Hidden instance.

  • GPlateContext a s => GPlate a sDefined in optics-core-0.4.1.1 · Optics.Generic
classclass GPosition (n :: Nat) s t a b | n s -> t a b, n t -> s a b where
#

Focus on a field at position n of type a within a type s using its Generic instance.

Example1 expression
('a', 'b', 'c') ^. gposition @2'b'
Example1 expression
('a', 'b') & gposition @1 .~ "hi" & gposition @2 .~ "there"("hi","there")
Example1 expression
('a', 'b', 'c') ^. gposition @4......Data constructor ‘(,,)’ has 3 fields, 4th requested...In the......
Example1 expression
() ^. gposition @1......Data constructor ‘()’ has no fields, 1st requested...In the......

Types without a Generic instance are not supported:

Example1 expression
NoG 'x' ^. gposition @1......Type ‘NoG’ doesn't have a Generic instance...In the......

Note: Positions start from 1:

Example1 expression
('a', 'b') ^. gposition @0......There is no 0th position...In the......

Methods

Instances2GPosition
  • GPositionContext repDefined n s t a b => GPosition n s t a bDefined in optics-core-0.4.1.1 · Optics.Generic
  • (a ~ Void0, b ~ Void0) => GPosition name Void0 Void0 a bDefined in optics-core-0.4.1.1 · Optics.Generic

    Hidden instance.

Re

Some optics can be reversed with re. This is mainly useful to invert Isos:

Example2 expressions
let _Identity = iso runIdentity Identityview (_1 % re _Identity) ('x', "yz")Identity 'x'

Yet we can use a Lens as a Review too:

Example1 expression
review (re _1) ('x', "yz")'x'

In the following diagram, red arrows illustrate how re transforms optics. The ReversedLens and ReversedPrism optic kinds are backwards versions of Lens and Prism respectively, and are present so that re . re does not change the optic kind.

Reversed Optics

classclass ReversibleOptic (k :: OpticKind) where
#

Class for optics that can be reversed.

Methods

Instances7ReversibleOptic, …
familytype family ReversedOptic (k :: OpticKind)
#
Instances7ReversedOptic, …

ReadOnly

Defines getting, which turns a read-write optic into its read-only counterpart.

classclass ToReadOnly (k :: OpticKind) s t a b where
#

Class for read-write optics that have their read-only counterparts.

Associated types

Methods

  • getting :: Optic k is s t a b -> Optic' (ReadOnlyOptic k) is s a

    Turn read-write optic into its read-only counterpart (or leave read-only optics as-is).

    This is useful when you have an optic :: Optic k is s t a b of read-write kind k such that s, t, a, b are rigid, there is no evidence that s ~ t and a ~ b and you want to pass optic to one of the functions that accept read-only optic kinds.

    Example:

    Example1 expression
    let fstIntToChar = _1 :: Lens (Int, r) (Char, r) Int Char
    Example1 expression
    :t view fstIntToChar......Couldn't match type ‘Char’ with ‘Int’...
    Example1 expression
    :t view (getting fstIntToChar)view (getting fstIntToChar) :: (Int, r) -> Int
Instances9ToReadOnly, …
familytype family ReadOnlyOptic (k :: OpticKind) :: OpticKind
#
Instances9ReadOnlyOptic, …

Mapping

Defines mapping through Functors

classclass MappingOptic (k :: OpticKind) (f :: Type -> Type) (g :: Type -> Type) s t a b where
#

Class for optics supporting mapping through a Functor.

Associated types

Methods

Instances7MappingOptic, …
familytype family MappedOptic (k :: OpticKind)
#

Type family that maps an optic to the optic kind produced by mapping using it.

Instances7MappedOptic, …

Setter utilities for working in Control.Monad.State.MonadState.

valueassign :: (Is k A_Setter, MonadState s m) => Optic k is s s a b -> b -> m ()
#

Replace the target(s) of an Optic in our monadic state with a new value, irrespective of the old.

Example1 expression
execState (do assign _1 'c'; assign _2 'd') ('a','b')('c','d')
Example1 expression
execState (assign each 'c') ('a','b')('c','c')
valueassign'
  1. :: (Is k A_Setter, MonadState s m)
  2. => Optic k is s s a b
  3. -> b
  4. -> m ()
#

Version of assign that is strict in both optic application and state modification.

Example1 expression
flip evalState ('a','b') $ assign _1 (errorWithoutStackTrace "oops")()
Example1 expression
flip evalState ('a','b') $ assign' _1 (errorWithoutStackTrace "oops")*** Exception: oops
valuemodifying
  1. :: (Is k A_Setter, MonadState s m)
  2. => Optic k is s s a b
  3. -> a -> b
  4. -> m ()
#

Map over the target(s) of an Optic in our monadic state.

Example1 expression
execState (do modifying _1 (*10); modifying _2 $ stimes 5) (6,"o")(60,"ooooo")
Example1 expression
execState (modifying each $ stimes 2) ("a","b")("aa","bb")
valuemodifying'
  1. :: (Is k A_Setter, MonadState s m)
  2. => Optic k is s s a b
  3. -> a -> b
  4. -> m ()
#

Version of modifying that is strict in both optic application and state modification.

Example1 expression
flip evalState ('a','b') $ modifying _1 (errorWithoutStackTrace "oops")()
Example1 expression
flip evalState ('a','b') $ modifying' _1 (errorWithoutStackTrace "oops")*** Exception: oops
valueuse :: (Is k A_Getter, MonadState s m) => Optic' k is s a -> m a
#

Use the target of a Lens, Iso, or Getter in the current state.

Example1 expression
evalState (use _1) ('a','b')'a'
Example1 expression
evalState (use _2) ("hello","world")"world"

View

A generalized view function gview, which returns a single result (like view) if the optic is a Getter, a Maybe result (like preview) if the optic is an AffineFold, or a monoidal summary of results (like foldOf) if the optic is a Fold. In addition, it works for any Control.Monad.Reader.MonadReader, not just (->).

Example1 expression
gview _1 ('x','y')'x'
Example1 expression
gview _Left (Left 'x')Just 'x'
Example1 expression
gview folded ["a", "b"]"ab"
Example1 expression
runReaderT (gview _1) ('x','y') :: IO Char'x'

This module is experimental. Using the more type-restricted variants is encouraged where possible.

classclass ViewableOptic (k :: OpticKind) r where
#

Generalized view (even more powerful than view from the lens library).

View the value(s) pointed to by an optic.

The type of the result depends on the optic. You get:

When in doubt, use specific, flavour restricted versions. This function is mostly useful for things such as passthrough.

Associated types

Methods

Instances9ViewableOptic, …
familytype family ViewResult (k :: OpticKind) r
#
Instances9ViewResult, …
valueguse
  1. :: (ViewableOptic k a, MonadState s m)
  2. => Optic' k is s a
  3. -> m (ViewResult k a)
#

Use the target of a Lens, Iso, or Getter in the current state, or use a summary of a Fold or Traversal that points to a monoidal value.

Example1 expression
evalState (guse _1) ('a','b')'a'
Example1 expression
evalState (guse _2) ("hello","world")"world"

Zoom

A class to zoom in, changing the Control.Monad.State.State supplied by many different monad transformers, potentially quite deep in a monad transformer stack.

Example1 expression
flip execState ('a','b') $ zoom _1 $ equality .= 'c'('c','b')
classclass (MonadState s m, MonadState t n) => Zoom (m :: Type -> Type) (n :: Type -> Type) s t | m -> s, n -> t, m t -> n, n s -> m where
#

This class allows us to zoom in, changing the State supplied by many different monad transformers, potentially quite deep in a monad transformer stack.

Its functions can be used to run a monadic action in a larger State than it was defined in, using a Lens', an AffineTraversal' or a Traversal'.

This is commonly used to lift actions in a simpler State Monad into a State Monad with a larger State type.

When used with a Traversal' over multiple values, the actions for each target are executed sequentially and the results are aggregated.

This can be used to edit pretty much any Monad transformer stack with a State in it!

Example1 expression
flip L.evalState ('a','b') $ zoom _1 $ use equality'a'
Example1 expression
flip S.execState ('a','b') $ zoom _1 $ equality .= 'c'('c','b')
Example1 expression
flip L.execState [(1,2),(3,4)] $ zoomMany traversed $ _2 %= (*10)[(1,20),(3,40)]
Example1 expression
flip S.runState [('a',"b"),('c',"d")] $ zoomMany traversed $ _2 <%= (\x -> x <> x)("bbdd",[('a',"bb"),('c',"dd")])
Example1 expression
flip S.evalState ("a","b") $ zoomMany each (use equality)"ab"

Methods

Instances10Zoom, …
classclass (MonadReader b m, MonadReader a n) => Magnify (m :: Type -> Type) (n :: Type -> Type) b a | m -> b, n -> a, m a -> n, n b -> m where
#

This class allows us to magnify part of the environment, changing the environment supplied by many different Monad transformers. Unlike zoom this can change the environment of a deeply nested Monad transformer.

Its functions can be used to run a monadic action in a larger environment than it was defined in, using a Getter or an AffineFold.

They act like local, but can in many cases change the type of the environment as well.

They're commonly used to lift actions in a simpler Reader Monad into a Monad with a larger environment type.

They can be used to edit pretty much any Monad transformer stack with an environment in it:

Example1 expression
(1,2) & magnify _2 (+1)3
Example1 expression
flip runReader (1,2) $ magnify _1 ask1
Example1 expression
flip runReader (1,2,[10..20]) $ magnifyMaybe (_3 % _tail) askJust [11,12,13,14,15,16,17,18,19,20]

Methods

Instances11Magnify, …
classclass (MonadReader b m, MonadReader a n, Magnify m n b a) => MagnifyMany (m :: Type -> Type) (n :: Type -> Type) b a | m -> b, n -> a, m a -> n, n b -> m where
#

Extends Magnify with an ability to magnify using a Fold over multiple targets so that actions for each one are executed sequentially and the results are aggregated.

There is however no sensible instance of MagnifyMany for StateT.

Methods

Instances9MagnifyMany, …

Indexed optics

113 declarations

The optics library also provides indexed optics, which provide an additional index value in mappings:

over  :: Setter     s t a b -> (a -> b)      -> s -> t
iover :: IxSetter i s t a b -> (i -> a -> b) -> s -> t

Note that there aren't any laws about indices. Especially in compositions the same index may occur multiple times.

The machinery builds on indexed variants of Functor, Foldable, and Traversable classes: FunctorWithIndex, FoldableWithIndex and TraversableWithIndex respectively. There are instances for types in the boot libraries.

class (FoldableWithIndex i t, Traversable t)
  => TraversableWithIndex i t | t -> i where
    itraverse :: Applicative f => (i -> a -> f b) -> t a -> f (t b)

Indexed optics can be used as regular ones, i.e. indexed optics gracefully downgrade to regular ones.

Example1 expression
toListOf ifolded "foo""foo"
Example1 expression
itoListOf ifolded "foo"[(0,'f'),(1,'o'),(2,'o')]

But there is also a combinator noIx to explicitly erase indices:

Example1 expression
:t (ifolded % simple)(ifolded % simple)  :: FoldableWithIndex i f => Optic A_Fold '[i] (f b) (f b) b b
Example1 expression
:t noIx (ifolded % simple)noIx (ifolded % simple)  :: FoldableWithIndex i f => Optic A_Fold NoIx (f b) (f b) b b
λ> :t noIx (ifolded % ifolded)
noIx (ifolded % ifolded)
  :: (FoldableWithIndex i1 f1, FoldableWithIndex i2 f2) =>
     Optic A_Fold NoIx (f1 (f2 b)) (f1 (f2 b)) b b

As the example above illustrates, regular and indexed optics have the same tag in the first parameter of Optic, in this case A_Fold. Regular optics simply don't have any indices. The provided type aliases IxLens, IxGetter, IxAffineTraversal, IxAffineFold, IxTraversal, IxFold and IxSetter are variants with a single index. In general, the second parameter of the Optic newtype is a type-level list of indices, which will typically be NoIx (the empty index list) or (WithIx i) (a singleton list).

When two optics are composed with (%), the index lists are concatenated. Thus composing an unindexed optic with an indexed optic preserves the indices, or composing two indexed optics retains both indices:

λ> :t (ifolded % ifolded)
(ifolded % ifolded)
  :: (FoldableWithIndex i1 f1, FoldableWithIndex i2 f2) =>
     Optic A_Fold '[i1, i2] (f1 (f2 b)) (f1 (f2 b)) b b

In order to use such an optic, it is necessary to flatten the indices into a single index using icompose or a similar function:

λ> :t icompose (,) (ifolded % ifolded)
icompose (,) (ifolded % ifolded)
  :: (FoldableWithIndex i1 f1, FoldableWithIndex i2 f2) =>
     Optic A_Fold (WithIx (i1, i2)) (f1 (f2 b)) (f1 (f2 b)) b b

For example:

Example1 expression
itoListOf (icompose (,) (ifolded % ifolded)) [['a','b'], ['c', 'd']][((0,0),'a'),((0,1),'b'),((1,0),'c'),((1,1),'d')]

Alternatively, you can use one of the (<%) or (%>) operators to compose indexed optics and pick the index to retain, or the (<%>) operator to retain a pair of indices:

Example1 expression
itoListOf (ifolded <% ifolded) [['a','b'], ['c', 'd']][(0,'a'),(0,'b'),(1,'c'),(1,'d')]
Example1 expression
itoListOf (ifolded %> ifolded) [['a','b'], ['c', 'd']][(0,'a'),(1,'b'),(0,'c'),(1,'d')]
Example1 expression
itoListOf (ifolded <%> ifolded) [['a','b'], ['c', 'd']][((0,0),'a'),((0,1),'b'),((1,0),'c'),((1,1),'d')]

In the diagram below, the optics hierarchy is amended with these (singly) indexed variants (in blue). Orange arrows mean "can be used as one, assuming it's composed with any optic below the orange arrow first". For example. _1 is not an indexed fold, but itraversed % _1 is, because it's an indexed traversal, so it's also an indexed fold.

Example2 expressions
let fst' = _1 :: Lens (a, c) (b, c) a b:t fst' % itraversedfst' % itraversed  :: TraversableWithIndex i f =>     Optic A_Traversal '[i] (f a, c) (f b, c) a b

Indexed Optics

datadata A_Lens
#

Tag for a lens.

Instances38ReversibleOptic, Is, ArrowOptic, ViewableOptic, PermeableOptic, JoinKinds, …
datadata A_Traversal
#

Tag for a traversal.

Instances31Is, ViewableOptic, PermeableOptic, JoinKinds, IxOptic, ToReadOnly, …
datadata An_AffineTraversal
#

Tag for an affine traversal.

Instances33Is, ArrowOptic, ViewableOptic, PermeableOptic, JoinKinds, IxOptic, …
datadata A_Setter
#

Tag for a setter.

Instances17Is, JoinKinds, IxOptic, …
valueconjoined
  1. :: HasSingleIndex is i
  2. => Optic k NoIx s t a b
  3. -> Optic k is s t a b
  4. -> Optic k is s t a b
#

Construct a conjoined indexed optic that provides a separate code path when used without indices. Useful for defining indexed optics that are as efficient as their unindexed equivalents when used without indices.

Note: conjoined f g is well-defined if and only if f ≡ noIx g.

valueitoListOf
  1. :: (Is k A_Fold, HasSingleIndex is i)
  2. => Optic' k is s a
  3. -> s
  4. -> [(i, a)]
#

Fold with index to a list.

Example1 expression
itoListOf (folded % ifolded) ["abc", "def"][(0,'a'),(1,'b'),(2,'c'),(0,'d'),(1,'e'),(2,'f')]

Note: currently indexed optics can be used as non-indexed.

Example1 expression
toListOf (folded % ifolded) ["abc", "def"]"abcdef"
valueilensVL :: IxLensVL i s t a b -> IxLens i s t a b
#

Build an indexed lens from the van Laarhoven representation.

valueiadjoin
  1. :: (Is k A_Traversal, Is l A_Traversal, HasSingleIndex is i)
  2. => Optic' k is s a
  3. -> Optic' l is s a
  4. -> IxTraversal' i s a
#

Combine two disjoint indexed traversals into one.

Example1 expression
iover (_1 % itraversed `iadjoin` _2 % itraversed) (+) ([0, 0, 0], (3, 5))([0,1,2],(3,8))

Note: if the argument traversals are not disjoint, the result will not respect the IxTraversal laws, because it will visit the same element multiple times. See section 7 of Understanding Idiomatic Traversals Backwards and Forwards by Bird et al. for why this is illegal.

Example2 expressions
iview (ipartsOf (each `iadjoin` each)) ("x","y")([0,1,0,1],["x","y","x","y"])iset (ipartsOf (each `iadjoin` each)) (const ["a","b","c","d"]) ("x","y")("c","d")

For the IxFold version see isumming.

valueitraverseOf
  1. :: (Is k A_Traversal, Applicative f, HasSingleIndex is i)
  2. => Optic k is s t a b
  3. -> i -> a -> f b
  4. -> s
  5. -> f t
#

Map each element of a structure targeted by an IxTraversal (supplying the index), evaluate these actions from left to right, and collect the results.

This yields the van Laarhoven representation of an indexed traversal.

classclass (FunctorWithIndex i t, FoldableWithIndex i t, Traversable t) => TraversableWithIndex i (t :: Type -> Type) | t -> i where
#

A Traversable with an additional index.

An instance must satisfy a (modified) form of the Traversable laws:

itraverse (const Identity) ≡ Identity
fmap (itraverse f) . itraverse g ≡ getCompose . itraverse (\i -> Compose . fmap (f i) . g i)

Methods

Instances32TraversableWithIndex, …
typetype IxTraversalVL i s t a b = forall (f :: Type -> Type). Applicative f => (i -> a -> f b) -> s -> f t
#

Type synonym for a type-modifying van Laarhoven indexed traversal.

valueifailing
  1. :: (Is k A_Fold, Is l A_Fold, HasSingleIndex is1 i, HasSingleIndex is2 i)
  2. => Optic' k is1 s a
  3. -> Optic' l is2 s a
  4. -> IxFold i s a
#

Try the first IxFold. If it returns no entries, try the second one.

Example2 expressions
itoListOf (_1 % ifolded `ifailing` _2 % ifolded) (["a"], ["b","c"])[(0,"a")]itoListOf (_1 % ifolded `ifailing` _2 % ifolded) ([], ["b","c"])[(0,"b"),(1,"c")]
valueisets :: ((i -> a -> b) -> s -> t) -> IxSetter i s t a b
#

Build an indexed setter from a function to modify the element(s).

classclass Functor f => FunctorWithIndex i (f :: Type -> Type) | f -> i where
#

A Functor with an additional index.

Instances must satisfy a modified form of the Functor laws:

imap f . imap g ≡ imap (\i -> f i . g i)
imap (\_ a -> a) ≡ id

Methods

  • imap :: (i -> a -> b) -> f a -> f b

    Map with access to the index.

Instances34FunctorWithIndex, …
datadata A_Fold
#

Tag for a fold.

Instances30Is, ViewableOptic, JoinKinds, IxOptic, ToReadOnly, ReadOnlyOptic, …
valueifindMOf
  1. :: (Is k A_Fold, Monad m, HasSingleIndex is i)
  2. => Optic' k is s a
  3. -> i -> a -> m Bool
  4. -> s
  5. -> m (Maybe (i, a))
#

The ifindMOf function takes an IxFold, a monadic predicate that is also supplied the index, a structure and returns in the monad the left-most element of the structure matching the predicate, or Nothing if there is no such element.

When you don't need access to the index then findMOf is more flexible in what it accepts.

valueifindOf
  1. :: (Is k A_Fold, HasSingleIndex is i)
  2. => Optic' k is s a
  3. -> i -> a -> Bool
  4. -> s
  5. -> Maybe (i, a)
#

The ifindOf function takes an IxFold, a predicate that is also supplied the index, a structure and returns the left-most element of the structure along with its index matching the predicate, or Nothing if there is no such element.

When you don't need access to the index then findOf is more flexible in what it accepts.

valueifolding :: FoldableWithIndex i f => (s -> f a) -> IxFold i s a
#

Obtain an IxFold by lifting an operation that returns a FoldableWithIndex result.

This can be useful to lift operations from Data.List and elsewhere into an IxFold.

Example1 expression
itoListOf (ifolding words) "how are you"[(0,"how"),(1,"are"),(2,"you")]
valueifoldring
  1. :: forall (f :: Type -> Type). Applicative f => (i -> a -> f u -> f u) -> f v -> s -> f w
  2. -> IxFold i s a
#

Obtain an IxFold by lifting ifoldr like function.

Example1 expression
itoListOf (ifoldring ifoldr) "hello"[(0,'h'),(1,'e'),(2,'l'),(3,'l'),(4,'o')]
classclass Foldable f => FoldableWithIndex i (f :: Type -> Type) | f -> i where
#

A container that supports folding with an additional index.

Methods

  • ifoldMap :: Monoid m => (i -> a -> m) -> f a -> m

    Fold a container by mapping value to an arbitrary Monoid with access to the index i.

    When you don't need access to the index then foldMap is more flexible in what it accepts.

    foldMap ≡ ifoldMap . const
    
  • ifoldMap' :: Monoid m => (i -> a -> m) -> f a -> m

    A variant of ifoldMap that is strict in the accumulator.

    When you don't need access to the index then foldMap' is more flexible in what it accepts.

    foldMap' ≡ ifoldMap' . const
    
  • ifoldr :: (i -> a -> b -> b) -> b -> f a -> b

    Right-associative fold of an indexed container with access to the index i.

    When you don't need access to the index then foldr is more flexible in what it accepts.

    foldr ≡ ifoldr . const
    
  • ifoldl :: (i -> b -> a -> b) -> b -> f a -> b

    Left-associative fold of an indexed container with access to the index i.

    When you don't need access to the index then foldl is more flexible in what it accepts.

    foldl ≡ ifoldl . const
    
  • ifoldr' :: (i -> a -> b -> b) -> b -> f a -> b

    Strictly fold right over the elements of a structure with access to the index i.

    When you don't need access to the index then foldr' is more flexible in what it accepts.

    foldr' ≡ ifoldr' . const
    
  • ifoldl' :: (i -> b -> a -> b) -> b -> f a -> b

    Fold over the elements of a structure with an index, associating to the left, but strictly.

    When you don't need access to the index then foldlOf' is more flexible in what it accepts.

    foldl' l ≡ ifoldl' l . const
    
Instances32FoldableWithIndex, …
datadata An_AffineFold
#

Tag for an affine fold.

Instances29Is, ViewableOptic, JoinKinds, IxOptic, ToReadOnly, ReadOnlyOptic, …
valueitraverse_
  1. :: (FoldableWithIndex i t, Applicative f)
  2. => i -> a -> f b
  3. -> t a
  4. -> f ()
#

Traverse elements with access to the index i, discarding the results.

When you don't need access to the index then traverse_ is more flexible in what it accepts.

traverse_ l = itraverse . const
typetype IxAffineTraversalVL i s t a b = forall (f :: Type -> Type). Functor f => (forall r. r -> f r) -> (i -> a -> f b) -> s -> f t
#

Type synonym for a type-modifying van Laarhoven indexed affine traversal.

Note: this isn't exactly van Laarhoven representation as there is no Pointed class (which would be a superclass of Applicative that contains pure but not <*>). You can interpret the first argument as a dictionary of Pointed that supplies the point function (i.e. the implementation of pure).

datadata A_Getter
#

Tag for a getter.

Instances31ReversibleOptic, Is, ViewableOptic, JoinKinds, IxOptic, ToReadOnly, …
valueito :: (s -> (i, a)) -> IxGetter i s a
#

Build an indexed getter from a function.

Example1 expression
iview (ito id) ('i', 'x')('i','x')
valuedevoid :: IxLens' i Void a
#

There is an indexed field for every type in the Void.

Example1 expression
set (mapped % devoid) 1 [][]
Example1 expression
over (_Just % devoid) abs NothingNothing
valueifst :: IxLens i (a, i) (b, i) a b
#

Indexed _1 with other half of a pair as an index.

See isnd for examples.

valueilens :: (s -> (i, a)) -> (s -> b -> t) -> IxLens i s t a b
#

Build an indexed lens from a getter and a setter.

If you want to build an IxLens from the van Laarhoven representation, use ilensVL.

valueisnd :: IxLens i (i, a) (i, b) a b
#

Indexed _2 with other half of a pair as an index. Specialized version of itraversed to pairs, which can be IxLens.

Example1 expression
iview isnd ('a', True)('a',True)

That is not possible with itraversed, because it is an IxTraversal.

Example1 expression
:t itraversed :: IxTraversal i (i, a) (i, b) a bitraversed :: IxTraversal i (i, a) (i, b) a b  :: IxTraversal i (i, a) (i, b) a b
typetype IxLensVL i s t a b = forall (f :: Type -> Type). Functor f => (i -> a -> f b) -> s -> f t
#

Type synonym for a type-modifying van Laarhoven indexed lens.

typetype IxLensVL' i s a = IxLensVL i s s a a
#

Type synonym for a type-preserving van Laarhoven indexed lens.

valueifor_
  1. :: (FoldableWithIndex i t, Applicative f)
  2. => t a
  3. -> i -> a -> f b
  4. -> f ()
#

Traverse elements with access to the index i, discarding the results (with the arguments flipped).

ifor_ ≡ flip itraverse_

When you don't need access to the index then for_ is more flexible in what it accepts.

for_ a ≡ ifor_ a . const
valueitoList :: FoldableWithIndex i f => f a -> [(i, a)]
#

Extract the key-value pairs from a structure.

When you don't need access to the indices in the result, then toList is more flexible in what it accepts.

toList ≡ map snd . itoList
value(%>)
  1. :: (JoinKinds k l m, IxOptic k s t u v, NonEmptyIndices is)
  2. => Optic k is s t u v
  3. -> Optic l js u v a b
  4. -> Optic m js s t a b
#

Compose two indexed optics and drop indices of the left one. (If you want to compose a non-indexed and an indexed optic, you can just use (%).)

Example1 expression
itoListOf (ifolded %> ifolded) ["foo", "bar"][(0,'f'),(1,'o'),(2,'o'),(0,'b'),(1,'a'),(2,'r')]
value(<%)
  1. :: (JoinKinds k l m, IxOptic l u v a b, NonEmptyIndices js)
  2. => Optic k is s t u v
  3. -> Optic l js u v a b
  4. -> Optic m is s t a b
#

Compose two indexed optics and drop indices of the right one. (If you want to compose an indexed and a non-indexed optic, you can just use (%).)

Example1 expression
itoListOf (ifolded <% ifolded) ["foo", "bar"][(0,'f'),(0,'o'),(0,'o'),(1,'b'),(1,'a'),(1,'r')]
value(<%>)
  1. :: (JoinKinds k l m, IxOptic m s t a b, HasSingleIndex is i, HasSingleIndex js j)
  2. => Optic k is s t u v
  3. -> Optic l js u v a b
  4. -> Optic m (WithIx (i, j)) s t a b
#

Compose two indexed optics. Their indices are composed as a pair.

Example1 expression
itoListOf (ifolded <%> ifolded) ["foo", "bar"][((0,0),'f'),((0,1),'o'),((0,2),'o'),((1,0),'b'),((1,1),'a'),((1,2),'r')]
valueicompose
  1. :: i -> j -> ix
  2. -> Optic k '[i, j] s t a b
  3. -> Optic k (WithIx ix) s t a b
#

Flatten indices obtained from two indexed optics.

Example1 expression
itoListOf (ifolded % ifolded %& icompose (,)) ["foo","bar"][((0,0),'f'),((0,1),'o'),((0,2),'o'),((1,0),'b'),((1,1),'a'),((1,2),'r')]
valueicompose3
  1. :: i1 -> i2 -> i3 -> ix
  2. -> Optic k '[i1, i2, i3] s t a b
  3. -> Optic k (WithIx ix) s t a b
#

Flatten indices obtained from three indexed optics.

Example1 expression
itoListOf (ifolded % ifolded % ifolded %& icompose3 (,,)) [["foo","bar"],["xyz"]][((0,0,0),'f'),((0,0,1),'o'),((0,0,2),'o'),((0,1,0),'b'),((0,1,1),'a'),((0,1,2),'r'),((1,0,0),'x'),((1,0,1),'y'),((1,0,2),'z')]
valueicompose4
  1. :: i1 -> i2 -> i3 -> i4 -> ix
  2. -> Optic k '[i1, i2, i3, i4] s t a b
  3. -> Optic k (WithIx ix) s t a b
#

Flatten indices obtained from four indexed optics.

valueicompose5
  1. :: i1 -> i2 -> i3 -> i4 -> i5 -> ix
  2. -> Optic k '[i1, i2, i3, i4, i5] s t a b
  3. -> Optic k (WithIx ix) s t a b
#

Flatten indices obtained from five indexed optics.

valuereindexed
  1. :: HasSingleIndex is i
  2. => i -> j
  3. -> Optic k is s t a b
  4. -> Optic k (WithIx j) s t a b
#

Remap the index.

Example1 expression
itoListOf (reindexed succ ifolded) "foo"[(1,'f'),(2,'o'),(3,'o')]
Example1 expression
itoListOf (ifolded %& reindexed succ) "foo"[(1,'f'),(2,'o'),(3,'o')]
classclass IxOptic (k :: OpticKind) s t a b where
#

Class for optic kinds that can have indices.

Methods

Instances7IxOptic, …

Monoid structures

0 declarations

There are two ways to combine (possibly indexed) folds, traversals and related optics with the same outer and inner types:

  • Visit all the targets of the first optic, then all the targets of the second optic. This makes sense for folds (summing or isumming) and traversals (adjoin or iadjoin), provided in the latter case that the targets are disjoint.

  • Visit the targets of the first optic if there are any, or if not, visit the targets of the second optic. This makes sense for folds (failing or ifailing) and affine folds (afailing or iafailing).

These operations form monoid structures on the appropriate optic kinds, with the identity element ignored, which visits no targets.

There is no Semigroup or Monoid instance for Optic, because there is not a unique choice of monoid to use, and the (<>) operator could not be used to combine optics of different kinds. When porting code from lens that uses (<>) to combine folds, use summing instead.

Generation of optics

0 declarations

...with Template Haskell

typetype ClassyNamer = Name -> Maybe (Name, Name)
#

The optional rule to create a class and method around a monomorphic data type. If this naming convention is provided, it generates a "classy" lens.

datadata DefName
#

Name to give to generated field optics.

Constructors

Instances3Eq, Ord, Show
  • Eq DefNameDefined in optics-th-0.4.1 · Optics.TH.Internal.Product
  • Ord DefNameDefined in optics-th-0.4.1 · Optics.TH.Internal.Product
  • Show DefNameDefined in optics-th-0.4.1 · Optics.TH.Internal.Product
typetype FieldNamer = Name -> [Name] -> Name -> [DefName]
#

The rule to create function names of lenses for data fields.

Although it's sometimes useful, you won't need the first two arguments most of the time.

datadata LensRules
#

Rules to construct lenses for data fields.

valuemakeClassyPrisms
  1. :: Name

    Type constructor name

  2. -> DecsQ
#

Generate a Prism for each constructor of a data type and combine them into a single class. No Isos are created. Reviews are created for constructors with existentially quantified constructors and GADTs.

e.g.

data FooBarBaz a
  = Foo Int
  | Bar a
  | Baz Int Char
makeClassyPrisms ''FooBarBaz

will create

class AsFooBarBaz s a | s -> a where
  _FooBarBaz :: Prism' s (FooBarBaz a)
  _Foo :: Prism' s Int
  _Bar :: Prism' s a
  _Baz :: Prism' s (Int,Char)

  _Foo = _FooBarBaz % _Foo
  _Bar = _FooBarBaz % _Bar
  _Baz = _FooBarBaz % _Baz

instance AsFooBarBaz (FooBarBaz a) a

Generate an As class of prisms. Names are selected by prefixing the constructor name with an underscore. Constructors with multiple fields will construct Prisms to tuples of those fields.

valuemakePrisms
  1. :: Name

    Type constructor name

  2. -> DecsQ
#

Generate a Prism for each constructor of a data type. Isos generated when possible. Reviews are created for constructors with existentially quantified constructors and GADTs.

e.g.

data FooBarBaz a
  = Foo Int
  | Bar a
  | Baz Int Char
makePrisms ''FooBarBaz

will create

_Foo :: Prism' (FooBarBaz a) Int
_Bar :: Prism (FooBarBaz a) (FooBarBaz b) a b
_Baz :: Prism' (FooBarBaz a) (Int, Char)

Field rules fields in the form prefixFieldname or _prefixFieldname If you want all fields to be lensed, then there is no reason to use an _ before the prefix. If any of the record fields leads with an _ then it is assume a field without an _ should not have a lens created.

Note that prefix may be any string of characters that are not uppercase letters. (In particular, it may be arbitrary string of lowercase letters and numbers) This is the behavior that defaultFieldRules had in lens 4.4 and earlier.

Field rules for fields in the form prefixFieldname or _prefixFieldname

If you want all fields to be lensed, then there is no reason to use an _ before the prefix. If any of the record fields leads with an _ then it is assume a field without an _ should not have a lens created.

Note: The prefix must be the same as the typename (with the first letter lowercased). This is a change from lens versions before lens 4.5. If you want the old behaviour, use makeLensesWith abbreviatedFields

Field rules for fields in the form _fieldname (the leading underscore is mandatory).

Note: The primary difference to camelCaseFields is that for classUnderscoreNoPrefixFields the field names are not expected to be prefixed with the type name. This might be the desired behaviour when the DuplicateRecordFields extension is enabled.

valueclassyRulesFor
  1. :: (String -> Maybe (String, String))

    Type Name -> Maybe (Class Name, Method Name)

  2. -> [(String, String)]
    (Field Name, Method Name)
  3. -> LensRules
#

Rules for making lenses and traversals that precompose another Lens using a custom function for naming the class, main class method, and a mapping from field names to definition names.

valuedeclareClassy :: DecsQ -> DecsQ
#

For each record in the declaration quote, make lenses and traversals for it, and create a class when the type has no arguments. All record syntax in the input will be stripped off.

e.g.

declareClassy [d|
  data Foo = Foo { fooX, fooY :: Int }
    deriving Show
  |]

will create

data Foo = Foo Int Int deriving Show
class HasFoo t where
  foo :: Lens' t Foo
instance HasFoo Foo where foo = id
fooX, fooY :: HasFoo t => Lens' t Int

Make field optics as labels for all records in the given declaration quote. All record syntax in the input will be stripped off.

e.g.

declareLenses [d|
  data Dog = Dog { name :: String, age :: Int }
    deriving Show
  |]

will create

data Dog = Dog String Int
  deriving Show
instance (k ~ A_Lens, ...) => LabelOptic "name" k Dog Dog ...
instance (k ~ A_Lens, ...) => LabelOptic "age" k Dog Dog ...
valuedeclareLenses :: DecsQ -> DecsQ
#

Make field optics for all records in the given declaration quote. All record syntax in the input will be stripped off.

e.g.

declareLenses [d|
  data Foo = Foo { fooX, fooY :: Int }
    deriving Show
  |]

will create

data Foo = Foo Int Int deriving Show
fooX, fooY :: Lens' Foo Int
valuedeclarePrisms :: DecsQ -> DecsQ
#

Generate a Prism for each constructor of each data type.

e.g.

declarePrisms [d|
  data Exp = Lit Int | Var String | Lambda{ bound::String, body::Exp }
  |]

will create

data Exp = Lit Int | Var String | Lambda { bound::String, body::Exp }
_Lit :: Prism' Exp Int
_Var :: Prism' Exp String
_Lambda :: Prism' Exp (String, Exp)

Generate optics using lazy pattern matches. This can allow fields of an undefined value to be initialized with lenses:

data Foo = Foo {_x :: Int, _y :: Bool}
  deriving Show

makeLensesWith (lensRules & generateLazyPatterns .~ True) ''Foo
> undefined & x .~ 8 & y .~ True
Foo {_x = 8, _y = True}

The downside of this flag is that it can lead to space-leaks and code-size/compile-time increases when generated for large records. By default this flag is turned off, and strict optics are generated.

When using lazy optics the strict optic can be recovered by composing with equality':

strictOptic = equality' % lazyOptic

Indicate whether or not to supply the signatures for the generated lenses.

Disabling this can be useful if you want to provide a more restricted type signature or if you want to supply hand-written haddocks.

Generate "updateable" optics when True. When False, (affine) folds will be generated instead of (affine) traversals and getters will be generated instead of lenses. This mode is intended to be used for types with invariants which must be maintained by "smart" constructors.

valuemakeClassy :: Name -> DecsQ
#

Make lenses and traversals for a type, and create a class when the type has no arguments.

e.g.

data Foo = Foo { _fooX, _fooY :: Int }
makeClassy ''Foo

will create

class HasFoo c where
  foo  :: Lens' c Foo
  fooX :: Lens' c Int
  fooY :: Lens' c Int
  fooX = foo % fooX
  fooY = foo % fooY

instance HasFoo Foo where
  foo  = lensVL id
  fooX = lensVL $ \f s -> case s of
    Foo x1 x2 -> fmap (\y -> Foo y x2) (f x1)
  fooY = lensVL $ \f s -> case s of
    Foo x1 x2 -> fmap (\y -> Foo x1 y) (f x2)
makeClassy = makeLensesWith classyRules
valuemakeClassy_ :: Name -> DecsQ
#

Make lenses and traversals for a type, and create a class when the type has no arguments. Works the same as makeClassy except that (a) it expects that record field names do not begin with an underscore, (b) all record fields are made into lenses, and (c) the resulting lens is prefixed with an underscore.

valuemakeFieldLabels :: Name -> DecsQ
#

Build field optics as instances of the LabelOptic class for use with overloaded labels. See Optics.Label for how to use this pattern.

e.g.

data Animal
  = Cat { animalAge  :: Int
        , animalName :: String
        }
  | Dog { animalAge    :: Int
        , animalAbsurd :: forall a b. a -> b
        }
makeFieldLabels ''Animal

will create

instance
  (k ~ A_Lens, a ~ Int, b ~ Int
  ) => LabelOptic "age" k Animal Animal a b where
  labelOptic = lensVL $ \f s -> case s of
    Cat x1 x2 -> fmap (\y -> Cat y x2) (f x1)
    Dog x1 x2 -> fmap (\y -> Dog y x2) (f x1)

instance
  (k ~ An_AffineTraversal, a ~ String, b ~ String
  ) => LabelOptic "name" k Animal Animal a b where
  labelOptic = atraversalVL $ \point f s -> case s of
    Cat x1 x2 -> fmap (\y -> Cat x1 y) (f x2)
    Dog x1 x2 -> point (Dog x1 x2)

instance
  ( Dysfunctional "absurd" k Animal Animal a b
  , k ~ An_AffineFold, a ~ (x -> y), b ~ (x -> y)
  ) => LabelOptic "absurd" k Animal Animal a b where
  labelOptic = afolding $ \s -> case s of
    Cat _ _  -> Nothing
    Dog _ f  -> Just f

which can be used as #age, #name and #absurd with the OverloadedLabels language extension.

Note: if you wonder about the structure of instances, see Optics.Label#structure.

makeFieldOptics = makeFieldLabelsWith fieldLabelsRules
valuemakeFields :: Name -> DecsQ
#

Generate overloaded field accessors.

e.g

data Foo a = Foo { _fooX :: Int, _fooY :: a }
newtype Bar = Bar { _barX :: Char }
makeFields ''Foo
makeFields ''Bar

will create

class HasX s a | s -> a where
  x :: Lens' s a

instance HasX (Foo a) Int where
  x = lensVL $ \f s -> case s of
    Foo x1 x2 -> fmap (\y -> Foo y x2) (f x1)

class HasY s a | s -> a where
  y :: Lens' s a

instance HasY (Foo a) a where
  y = lensVL $ \f s -> case s of
    Foo x1 x2 -> fmap (\y -> Foo x1 y) (f x2)

instance HasX Bar Char where
  x = lensVL $ \f s -> case s of
    Bar x1 -> fmap (\y -> Bar y) (f x1)

For details, see camelCaseFields.

makeFields = makeLensesWith defaultFieldRules

Generate overloaded field accessors based on field names which are only prefixed with an underscore (e.g. _name), not additionally with the type name (e.g. _fooName).

This might be the desired behaviour in case the DuplicateRecordFields language extension is used in order to get rid of the necessity to prefix each field name with the type name.

As an example:

data Foo a  = Foo { _x :: Int, _y :: a }
newtype Bar = Bar { _x :: Char }
makeFieldsNoPrefix ''Foo
makeFieldsNoPrefix ''Bar

will create classes

class HasX s a | s -> a where
  x :: Lens' s a
class HasY s a | s -> a where
  y :: Lens' s a

together with instances

instance HasX (Foo a) Int
instance HasY (Foo a) a where
instance HasX Bar Char where

For details, see classUnderscoreNoPrefixFields.

makeFieldsNoPrefix = makeLensesWith classUnderscoreNoPrefixFields
valuemakeLenses :: Name -> DecsQ
#

Build field optics as top level functions with a sensible default configuration.

e.g.

data Animal
  = Cat { _age  :: Int
        , _name :: String
        }
  | Dog { _age    :: Int
        , _absurd :: forall a b. a -> b
        }
makeLenses ''Animal

will create

absurd :: forall a b. AffineFold Animal (a -> b)
absurd = afolding $ \s -> case s of
  Cat _ _ -> Nothing
  Dog _ x -> Just x

age :: Lens' Animal Int
age = lensVL $ \f s -> case s of
  Cat x1 x2 -> fmap (\y -> Cat y x2) (f x1)
  Dog x1 x2 -> fmap (\y -> Dog y x2) (f x1)

name :: AffineTraversal' Animal String
name = atraversalVL $ \point f s -> case s of
  Cat x1 x2 -> fmap (\y -> Cat x1 y) (f x2)
  Dog x1 x2 -> point (Dog x1 x2)
makeLenses = makeLensesWith lensRules
valuemakeLensesFor :: [(String, String)] -> Name -> DecsQ
#

Derive field optics, specifying explicit pairings of (fieldName, opticName).

If you map multiple fields to the same optic and it is present in the same constructor, Traversal (or Fold for a read only version) will be generated.

e.g.

makeLensesFor [("_foo", "fooLens"), ("baz", "lbaz")] ''Foo
makeLensesFor [("_barX", "bar"), ("_barY", "bar")] ''Bar

Field rules for fields without any prefix. Useful for generation of field labels when paired with DuplicateRecordFields language extension so that no prefixes for field names are necessary.

A FieldNamer that leaves the field name as-is. Useful for generation of field labels when paired with DuplicateRecordFields language extension so that no prefixes for field names are necessary.

...with OverloadedLabels

classclass LabelOptic (name :: Symbol) (k :: OpticKind) s t a b | name s -> k a, name t -> k b, name s b -> t, name t a -> s where
#

Support for overloaded labels as optics.

An overloaded label #foo can be used as an optic if there is an instance LabelOptic "foo" k s t a b.

Alternatively, if both s and t have a Generic (GenericLabelOptics if explicit-generic-labels flag is enabled) instance, a total field of s is accessible by a label #field of kind A_Lens, whereas its constructor by a label #_Constructor of kind A_Prism.

Methods

Instances2LabelOptic
  • GenericLabelOpticContext repDefined name k s t a b => LabelOptic name k s t a bDefined in optics-core-0.4.1.1 · Optics.Label

    If no instance matches, try to use Generic machinery for field access.

    For more information have a look at gfield and gconstructor.

  • (k ~ An_Iso, a ~ Void0, b ~ Void0) => LabelOptic name k Void0 Void0 a bDefined in optics-core-0.4.1.1 · Optics.Label

    If for an overloaded label #label there is no instance starting with LabelOptic "label" in scope, using it in the context of optics makes GHC immediately pick the overlappable instance defined below (since no other instance could match). If at this point GHC has no information about s or t, it ends up picking incoherent instance of GenericLabelOptic defined below. Prevent that (if only to be able to inspect most polymorphic types of #foo % #bar or view #foo in GHCi) by defining a dummy instance that matches all names, thus postponing instance resolution until s or t is known.

classclass Generic a => GenericLabelOptics a where
#

If the explicit-generic-labels Cabal flag is enabled, only types with this instance (which can be trivially derived with DeriveAnyClass extension) will be able to use labels as generic optics with a specific type.

It's an option for application developers to disable implicit fallback to generic optics for more control.

Libraries using generic labels with their data types should derive this instance for compatibility with the explicit-generic-labels flag.

Note: the flag explicit-generic-labels is disabled by default. Enabling it is generally unsupported as it might lead to compilation errors of dependencies relying on implicit fallback to generic optics.

Associated types

Optics for concrete base types

23 declarations
classclass Field1 s t a b | s -> a, t -> b, s b -> t, t a -> s where
#

Provides access to 1st field of a tuple.

Methods

  • _1 :: Lens s t a b

    Access the 1st field of a tuple (and possibly change its type).

    Example1 expression
    (1,2) ^. _11
    Example1 expression
    (1,2) & _1 .~ "hello"("hello",2)
    Example1 expression
    traverseOf _1 putStrLn ("hello","world")hello((),"world")

    This can also be used on larger tuples as well:

    Example1 expression
    (1,2,3,4,5) & _1 %~ (+41)(42,2,3,4,5)
Instances11Field1, …
  • Field1 (Identity a) (Identity b) a bDefined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field1 (a, b) (a', b) a a'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field1 (a, b, c) (a', b, c) a a'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field1 (a, b, c, d) (a', b, c, d) a a'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field1 (Product f g a) (Product f' g a) (f a) (f' a)Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field1 ((:*:) f g p) ((:*:) f' g p) (f p) (f' p)Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field1 (a, b, c, d, e) (a', b, c, d, e) a a'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field1 (a, b, c, d, e, f) (a', b, c, d, e, f) a a'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field1 (a, b, c, d, e, f, g) (a', b, c, d, e, f, g) a a'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field1 (a, b, c, d, e, f, g, h) (a', b, c, d, e, f, g, h) a a'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field1 (a, b, c, d, e, f, g, h, i) (a', b, c, d, e, f, g, h, i) a a'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
classclass Field2 s t a b | s -> a, t -> b, s b -> t, t a -> s where
#

Provides access to the 2nd field of a tuple.

Methods

  • _2 :: Lens s t a b

    Access the 2nd field of a tuple.

    Example1 expression
    _2 .~ "hello" $ (1,(),3,4)(1,"hello",3,4)
    Example1 expression
    (1,2,3,4) & _2 %~ (*3)(1,6,3,4)
    Example1 expression
    traverseOf _2 print (1,2)2(1,())
Instances10Field2, …
  • Field2 (a, b) (a, b') b b'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field2 (a, b, c) (a, b', c) b b'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field2 (a, b, c, d) (a, b', c, d) b b'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field2 (Product f g a) (Product f g' a) (g a) (g' a)Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field2 ((:*:) f g p) ((:*:) f g' p) (g p) (g' p)Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field2 (a, b, c, d, e) (a, b', c, d, e) b b'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field2 (a, b, c, d, e, f) (a, b', c, d, e, f) b b'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field2 (a, b, c, d, e, f, g) (a, b', c, d, e, f, g) b b'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field2 (a, b, c, d, e, f, g, h) (a, b', c, d, e, f, g, h) b b'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field2 (a, b, c, d, e, f, g, h, i) (a, b', c, d, e, f, g, h, i) b b'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
classclass Field3 s t a b | s -> a, t -> b, s b -> t, t a -> s where
#

Provides access to the 3rd field of a tuple.

Methods

  • _3 :: Lens s t a b

    Access the 3rd field of a tuple.

Instances7Field3, …
  • Field3 (a, b, c) (a, b, c') c c'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field3 (a, b, c, d) (a, b, c', d) c c'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field3 (a, b, c, d, e) (a, b, c', d, e) c c'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field3 (a, b, c, d, e, f) (a, b, c', d, e, f) c c'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field3 (a, b, c, d, e, f, g) (a, b, c', d, e, f, g) c c'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field3 (a, b, c, d, e, f, g, h) (a, b, c', d, e, f, g, h) c c'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field3 (a, b, c, d, e, f, g, h, i) (a, b, c', d, e, f, g, h, i) c c'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
classclass Field4 s t a b | s -> a, t -> b, s b -> t, t a -> s where
#

Provide access to the 4th field of a tuple.

Methods

  • _4 :: Lens s t a b

    Access the 4th field of a tuple.

Instances6Field4
  • Field4 (a, b, c, d) (a, b, c, d') d d'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field4 (a, b, c, d, e) (a, b, c, d', e) d d'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field4 (a, b, c, d, e, f) (a, b, c, d', e, f) d d'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field4 (a, b, c, d, e, f, g) (a, b, c, d', e, f, g) d d'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field4 (a, b, c, d, e, f, g, h) (a, b, c, d', e, f, g, h) d d'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field4 (a, b, c, d, e, f, g, h, i) (a, b, c, d', e, f, g, h, i) d d'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
classclass Field5 s t a b | s -> a, t -> b, s b -> t, t a -> s where
#

Provides access to the 5th field of a tuple.

Methods

  • _5 :: Lens s t a b

    Access the 5th field of a tuple.

Instances5Field5
  • Field5 (a, b, c, d, e) (a, b, c, d, e') e e'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field5 (a, b, c, d, e, f) (a, b, c, d, e', f) e e'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field5 (a, b, c, d, e, f, g) (a, b, c, d, e', f, g) e e'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field5 (a, b, c, d, e, f, g, h) (a, b, c, d, e', f, g, h) e e'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field5 (a, b, c, d, e, f, g, h, i) (a, b, c, d, e', f, g, h, i) e e'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
classclass Field6 s t a b | s -> a, t -> b, s b -> t, t a -> s where
#

Provides access to the 6th element of a tuple.

Methods

  • _6 :: Lens s t a b

    Access the 6th field of a tuple.

Instances4Field6
  • Field6 (a, b, c, d, e, f) (a, b, c, d, e, f') f f'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field6 (a, b, c, d, e, f, g) (a, b, c, d, e, f', g) f f'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field6 (a, b, c, d, e, f, g, h) (a, b, c, d, e, f', g, h) f f'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field6 (a, b, c, d, e, f, g, h, i) (a, b, c, d, e, f', g, h, i) f f'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
classclass Field7 s t a b | s -> a, t -> b, s b -> t, t a -> s where
#

Provide access to the 7th field of a tuple.

Methods

  • _7 :: Lens s t a b

    Access the 7th field of a tuple.

Instances3Field7
  • Field7 (a, b, c, d, e, f, g) (a, b, c, d, e, f, g') g g'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field7 (a, b, c, d, e, f, g, h) (a, b, c, d, e, f, g', h) g g'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field7 (a, b, c, d, e, f, g, h, i) (a, b, c, d, e, f, g', h, i) g g'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
classclass Field8 s t a b | s -> a, t -> b, s b -> t, t a -> s where
#

Provide access to the 8th field of a tuple.

Methods

  • _8 :: Lens s t a b

    Access the 8th field of a tuple.

Instances2Field8
  • Field8 (a, b, c, d, e, f, g, h) (a, b, c, d, e, f, g, h') h h'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
  • Field8 (a, b, c, d, e, f, g, h, i) (a, b, c, d, e, f, g, h', i) h h'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics
classclass Field9 s t a b | s -> a, t -> b, s b -> t, t a -> s where
#

Provides access to the 9th field of a tuple.

Methods

  • _9 :: Lens s t a b

    Access the 9th field of a tuple.

Instances1Field9
  • Field9 (a, b, c, d, e, f, g, h, i) (a, b, c, d, e, f, g, h, i') i i'Defined in optics-core-0.4.1.1 · Data.Tuple.Optics

Cheat sheet

0 declarations

The following table summarizes the key optic kinds and their combinators. It is based on a similar table for the lens package.

A Lens can be used as a Getter, Setter, Fold and Traversal.

Combinator

Indexed

Notes

Getters

to

ito

Build a

Getter

/

IxGetter

from a plain function.

view

/

^.

iview

View a single target.

views

iviews

View after applying a function.

Setters

sets

isets

Build a

Setter

/

IxSetter

from an update function.

mapped

imapped

Build a

Setter

from the

Functor

class, or an

IxSetter

from

FunctorWithIndex

.

set

/

.~

iset

Replace target(s) with value.

over

/

%~

iover

Modify target(s) by applying a function.

Folds

folded

ifolded

Build a

Fold

from the

Foldable

class, or an

IxFold

from

FoldableWithIndex

.

toListOf

/

^..

itoListOf

Return a list of the target(s).

AffineFolds

afolding

iafolding

Build an

AffineFold

/

IxAffineFold

from a partial function.

preview

/

^?

ipreview

Match the target or return

Nothing

.

previews

ipreviews

Preview after applying a function.

Traversals

traversed

itraversed

Build a

Traversal

from the

Traversable

class, or an

IxTraversal

from

TraversableWithIndex

.

traverseOf

itraverseOf

Update target(s) with an

Applicative

.

Prisms

prism

Build a

Prism

from a constructor and matcher.

review

/

#

Use a

Prism

to construct the sum type.

For setting/modifying using a Setter, a variety of combinators are available in Optics.State and Optics.State.Operators. The latter are not exported by the main Optics module, so must be imported explicitly.

Lazy

Strict

Stateful

Stateful returning new value

Stateful returning old value

Notes

set

/

.~

set'

/

!~

assign

/

.=

<.=

<<.=

Replace target(s) with value.

over

/

%~

over'

/

%!~

modifying

/

%=

<%=

<<%=

Modify target(s) by applying a function.

?~

?!~

?=

<?=

<<?=

Replace target(s) with

Just

a value.