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

Modulelens-5.3.5Haskell2010

Control.Lens.Prism

  • 4 types
  • 3 classes
  • 19 values
  • Packagelens-5.3.5
  • Exports26
  • LanguageHaskell2010
  • LicenceBSD-2-Clause
  • SourceType.hs

Prisms

4 declarations
typetype Prism s t a b = forall (p :: Type -> Type -> Type) (f :: Type -> Type). (Choice p, Applicative f) => p a (f b) -> p s (f t)
#

A Prism l is a Traversal that can also be turned around with re to obtain a Getter in the opposite direction.

There are three laws that a Prism should satisfy:

First, if I re or review a value with a Prism and then preview or use (^?), I will get it back:

preview l (review l b) ≡ Just b

Second, if you can extract a value a using a Prism l from a value s, then the value s is completely described by l and a:

preview l s ≡ Just a ⟹ review l a ≡ s

Third, if you get non-match t, you can convert it result back to s:

Control.Lens.Combinators.matching l s ≡ Left t ⟹ Control.Lens.Combinators.matching l t ≡ Left s

The first two laws imply that the Traversal laws hold for every Prism and that we traverse at most 1 element:

lengthOf l x <= 1

It may help to think of this as an Iso that can be partial in one direction.

Every Prism is a valid Traversal.

Every Iso is a valid Prism.

For example, you might have a Prism' Integer Numeric.Natural.Natural allows you to always go from a Numeric.Natural.Natural to an Integer, and provide you with tools to check if an Integer is a Numeric.Natural.Natural and/or to edit one if it is.

nat :: Prism' Integer Numeric.Natural.Natural
nat = prism toInteger $ \ i ->
   if i < 0
   then Left i
   else Right (fromInteger i)

Now we can ask if an Integer is a Numeric.Natural.Natural.

Example1 expression
5^?natJust 5
Example1 expression
(-5)^?natNothing

We can update the ones that are:

Example1 expression
(-3,4) & both.nat *~ 2(-3,8)

And we can then convert from a Numeric.Natural.Natural to an Integer.

Example1 expression
5 ^. re nat -- :: Natural5

Similarly we can use a Prism to traverse the Left half of an Either:

Example1 expression
Left "hello" & _Left %~ lengthLeft 5

or to construct an Either:

Example1 expression
5^.re _LeftLeft 5

such that if you query it with the Prism, you will get your original input back.

Example1 expression
5^.re _Left ^? _LeftJust 5

Another interesting way to think of a Prism is as the categorical dual of a Lens -- a co-Lens, so to speak. This is what permits the construction of outside.

Note: Composition with a Prism is index-preserving.

Constructing Prisms

2 declarations
valueprism :: (b -> t) -> (s -> Either t a) -> Prism s t a b
#

Build a Control.Lens.Prism.Prism.

Either t a is used instead of Maybe a to permit the types of s and t to differ.

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.

Consuming Prisms

9 declarations
valuewithPrism :: APrism s t a b -> ((b -> t) -> (s -> Either t a) -> r) -> r
#

Convert APrism to the pair of functions that characterize it.

valueaside :: APrism s t a b -> Prism (e, s) (e, t) (e, a) (e, b)
#

Use a Prism to work over part of a structure.

valuebelow :: Traversable f => APrism' s a -> Prism' (f s) (f a)
#

lift a Prism through a Traversable functor, giving a Prism that matches only if all the elements of the container match the Prism.

Example1 expression
[Left 1, Right "foo", Left 4, Right "woot"]^..below _Right[]
Example1 expression
[Right "hail hydra!", Right "foo", Right "blah", Right "woot"]^..below _Right[["hail hydra!","foo","blah","woot"]]
valueisn't :: APrism s t a b -> s -> Bool
#

Check to see if this Prism doesn't match.

Example1 expression
isn't _Left (Right 12)True
Example1 expression
isn't _Left (Left 12)False
Example1 expression
isn't _Empty []False
isn't = not . Control.Lens.Extra.is
isn't = hasn't
valuematching :: APrism s t a b -> s -> Either t a
#

Retrieve the value targeted by a Prism or return the original value while allowing the type to change if it does not match.

Example1 expression
matching _Just (Just 12)Right 12
Example1 expression
matching _Just (Nothing :: Maybe Int) :: Either (Maybe Bool) IntLeft Nothing
valuematching' :: LensLike (Either a) s t a b -> s -> Either t a
#

Like matching, but also works for combinations of Lens and Prisms, and also Traversals.

Example1 expression
matching' (_2 . _Just) ('x', Just True)Right True
Example1 expression
matching' (_2 . _Just) ('x', Nothing :: Maybe Int) :: Either (Char, Maybe Bool) IntLeft ('x',Nothing)
Example1 expression
matching' traverse "" :: Either [Int] CharLeft []
Example1 expression
matching' traverse "xyz" :: Either [Int] CharRight 'x'

Common Prisms

10 declarations
value_Left
  1. :: (Choice p, Applicative f)
  2. => p a (f b)
  3. -> p (Either a c) (f (Either b c))
#

This Prism provides a Traversal for tweaking the Left half of an Either:

Example1 expression
over _Left (+1) (Left 2)Left 3
Example1 expression
over _Left (+1) (Right 2)Right 2
Example1 expression
Right 42 ^._Left :: String""
Example1 expression
Left "hello" ^._Left"hello"

It also can be turned around to obtain the embedding into the Left half of an Either:

Example1 expression
_Left # 5Left 5
Example1 expression
5^.re _LeftLeft 5
value_Right
  1. :: (Choice p, Applicative f)
  2. => p a (f b)
  3. -> p (Either c a) (f (Either c b))
#

This Prism provides a Traversal for tweaking the Right half of an Either:

Example1 expression
over _Right (+1) (Left 2)Left 2
Example1 expression
over _Right (+1) (Right 2)Right 3
Example1 expression
Right "hello" ^._Right"hello"
Example1 expression
Left "hello" ^._Right :: [Double][]

It also can be turned around to obtain the embedding into the Right half of an Either:

Example1 expression
_Right # 5Right 5
Example1 expression
5^.re _RightRight 5
value_Just :: (Choice p, Applicative f) => p a (f b) -> p (Maybe a) (f (Maybe b))
#

This Prism provides a Traversal for tweaking the target of the value of Just in a Maybe.

Example1 expression
over _Just (+1) (Just 2)Just 3

Unlike traverse this is a Prism, and so you can use it to inject as well:

Example1 expression
_Just # 5Just 5
Example1 expression
5^.re _JustJust 5

Interestingly,

m ^? _Just ≡ m
Example1 expression
Just x ^? _JustJust x
Example1 expression
Nothing ^? _JustNothing
value_Nothing
  1. :: (Choice p, Applicative f)
  2. => p () (f ())
  3. -> p (Maybe a) (f (Maybe a))
#

This Prism provides the Traversal of a Nothing in a Maybe.

Example1 expression
Nothing ^? _NothingJust ()
Example1 expression
Just () ^? _NothingNothing

But you can turn it around and use it to construct Nothing as well:

Example1 expression
_Nothing # ()Nothing
value_Show :: (Read a, Show a) => Prism' String a
#

This is an improper prism for text formatting based on Read and Show.

This Prism is "improper" in the sense that it normalizes the text formatting, but round tripping is idempotent given sane Read/Show instances.

Example1 expression
_Show # 2"2"
Example1 expression
"EQ" ^? _Show :: Maybe OrderingJust EQ
_Show ≡ prism' show readMaybe
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
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 [] Prelude.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.

classclass Prefixed t where
#

Methods

  • prefixed :: t -> Prism' t t

    A Prism stripping a prefix from a sequence when used as a Traversal, or prepending that prefix when run backwards:

    Example1 expression
    "preview" ^? prefixed "pre"Just "view"
    Example1 expression
    "review" ^? prefixed "pre"Nothing
    Example1 expression
    prefixed "pre" # "amble""preamble"
Instances5Prefixed
classclass Suffixed t where
#

Methods

  • suffixed :: t -> Prism' t t

    A Prism stripping a suffix from a sequence when used as a Traversal, or appending that suffix when run backwards:

    Example1 expression
    "review" ^? suffixed "view"Just "re"
    Example1 expression
    "review" ^? suffixed "tire"Nothing
    Example1 expression
    suffixed ".o" # "hello""hello.o"
Instances5Suffixed

Prismatic profunctors

1 declaration
classclass Profunctor p => Choice (p :: Type -> Type -> Type) where
#

The generalization of Costar of Functor that is strong with respect to Either.

Note: This is also a notion of strength, except with regards to another monoidal structure that we can choose to equip Hask with: the cocartesian coproduct.

Methods

Instances28Choice, …