type 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.
For example, you might have a Prism' Integer allows you to always
go from a Numeric.Natural.NaturalNumeric.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.
5^?natJust 5
(-5)^?natNothing
We can update the ones that are:
(-3,4) & both.nat *~ 2(-3,8)
And we can then convert from a Numeric.Natural.Natural to an Integer.
5 ^. re nat -- :: Natural5
Similarly we can use a Prism to traverse the Left half of an Either:
Left "hello" & _Left %~ lengthLeft 5
or to construct an Either:
5^.re _LeftLeft 5
such that if you query it with the Prism, you will get your original input back.
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.