lens-3.7.0.2: Lenses, Folds and Traversals

Portability non-portable provisional Edward Kmett Trustworthy

Control.Lens.Prism

Description

Synopsis

# Prisms

type Prism s t a b = forall k f. (Prismatic k, Applicative f) => k (a -> f b) (s -> f t)Source

A `Prism` `l` is a 0-or-1 target `Traversal` that can also be turned around with `remit` to obtain a `Getter` in the opposite direction.

There are two laws that a `Prism` should satisfy:

First, if I `remit` 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 my `l` and `a`:

• If `preview l s ≡ Just a` then `review l a ≡ s`

These 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 a `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 `Simple Prism Integer Natural` allows you to always go from a `Natural` to an `Integer`, and provide you with tools to check if an `Integer` is a `Natural` and/or to edit one if it is.

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

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

````>>> ````5^?nat
```Just 5
```
````>>> ````(-5)^?nat
```Nothing
```

We can update the ones that are:

````>>> ````(-3,4) & both.nat *~ 2
```(-3,8)
```

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

````>>> ````5 ^. remit nat -- :: Natural
```5
```

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

````>>> ````Left "hello" & _left %~ length
```Left 5
```

or to construct an `Either`:

````>>> ````5^.remit _left
```Left 5
```

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

````>>> ````5^.remit _left ^? _left
```Just 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`.

type APrism s t a b = Overloaded Prismoid Mutator s t a bSource

If you see this in a signature for a function, the function is expecting a `Prism`, not some kind of alien invader.

# Constructing Prisms

class Isomorphic k => Prismatic k whereSource

An instance of `Prismatic` is a `Category` with a canonical mapping to it from the category of embedding-projection pairs over Haskell types.

Methods

prism :: Applicative f => (b -> t) -> (s -> Either t a) -> k (a -> f b) (s -> f t)Source

Build a `Prism`.

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

Instances

 Prismatic (->) Prismatic Prismoid

data Prismoid ab st whereSource

This data type is used to capture all of the information provided by the `Prismatic` class, so you can turn a `Prism` around into a `Getter` or otherwise muck around with its internals.

If you see a function that expects a `Prismoid` or `APrism`, it is probably just expecting a `Prism`.

Constructors

 Prismoid :: Prismoid x x Prism :: (CoB x -> CoB y) -> (CoA y -> Either (CoB y) (CoA x)) -> Prismoid x y

Instances

 Category Prismoid Prismatic Prismoid Isomorphic Prismoid

# Consuming Prisms

clonePrism :: APrism s t a b -> Prism s t a bSource

Clone a `Prism` so that you can reuse the same monomorphically typed `Prism` for different purposes.

See `cloneLens` and `cloneTraversal` for examples of why you might want to do this.

remit :: APrism s t a b -> Getter b tSource

Turn a `Prism` or `Iso` around to build a `Getter`.

If you have an `Iso`, `from` is a more powerful version of this function that will return an `Iso` instead of a mere `Getter`.

````>>> ````5 ^.remit _left
```Left 5
```
``` `remit` :: `Prism` s t a b -> `Getter` b t
`remit` :: `Iso` s t a b   -> `Getter` b t
```

review :: MonadReader b m => APrism s t a b -> m tSource

This can be used to turn an `Iso` or `Prism` around and `view` a value (or the current environment) through it the other way.

``review` ≡ `view` `.` `remit``
````>>> ````review _left "mustard"
```Left "mustard"
```

Usually `review` is used in the `(->)` monad with a `Simple` `Prism` or `Iso`, in which case it may be useful to think of it as having one of these more restricted type signatures:

``` `review` :: `Simple` `Iso` s a        -> a -> s
`review` :: `Simple` `Prism` s a -> a -> s
```

However, when working with a monad transformer stack, it is sometimes useful to be able to `review` the current environment, in which case one of these more slightly more liberal type signatures may be beneficial to think of it as having:

``` `review` :: `MonadReader` a m => `Simple` `Iso` s a        -> m s
`review` :: `MonadReader` a m => `Simple` `Prism` s a -> m s
```

reviews :: MonadReader b m => APrism s t a b -> (t -> r) -> m rSource

This can be used to turn an `Iso` or `Prism` around and `view` a value (or the current environment) through it the other way, applying a function.

``reviews` ≡ `views` `.` `remit``
````>>> ````reviews _left isRight "mustard"
```False
```

Usually this function is used in the `(->)` monad with a `Simple` `Prism` or `Iso`, in which case it may be useful to think of it as having one of these more restricted type signatures:

``` `reviews` :: `Simple` `Iso` s a        -> (s -> r) -> a -> r
`reviews` :: `Simple` `Prism` s a -> (s -> r) -> a -> r
```

However, when working with a monad transformer stack, it is sometimes useful to be able to `review` the current environment, in which case one of these more slightly more liberal type signatures may be beneficial to think of it as having:

``` `reviews` :: `MonadReader` a m => `Simple` `Iso` s a        -> (s -> r) -> m r
`reviews` :: `MonadReader` a m => `Simple` `Prism` s a -> (s -> r) -> m r
```

reuse :: MonadState b m => APrism s t a b -> m tSource

This can be used to turn an `Iso` or `Prism` around and `use` a value (or the current environment) through it the other way.

``reuse` ≡ `use` `.` `remit``
````>>> ````evalState (reuse _left) 5
```Left 5
```
``` `reuse` :: `MonadState` a m => `Simple` `Prism` s a -> m s
`reuse` :: `MonadState` a m => `Simple` `Iso` s a        -> m s
```

reuses :: MonadState b m => APrism s t a b -> (t -> r) -> m rSource

This can be used to turn an `Iso` or `Prism` around and `use` the current state through it the other way, applying a function.

``reuses` ≡ `uses` `.` `remit``
````>>> ````evalState (reuses _left isLeft) (5 :: Int)
```True
```
``` `reuses` :: `MonadState` a m => `Simple` `Prism` s a -> (s -> r) -> m r
`reuses` :: `MonadState` a m => `Simple` `Iso` s a        -> (s -> r) -> m r
```

outside :: APrism s t a b -> Lens (t -> r) (s -> r) (b -> r) (a -> r)Source

Use a `Prism` as a kind of first-class pattern.

``outside` :: `Prism` s t a b -> `Lens` (t -> r) (s -> r) (b -> r) (a -> r)`

aside :: APrism s t a b -> Prism (e, s) (e, t) (e, a) (e, b)Source

Use a `Prism` to work over part of a structure.

without :: APrism s t a b -> APrism u v c d -> Prism (Either s u) (Either t v) (Either a c) (Either b d)Source

Given a pair of prisms, project sums.

Viewing a `Prism` as a co-lens, this combinator can be seen to be dual to `alongside`.

# Common Prisms

_left :: Prism (Either a c) (Either b c) a bSource

This prism provides a traversal for tweaking the left-hand value of an `Either`:

````>>> ````over _left (+1) (Left 2)
```Left 3
```
````>>> ````over _left (+1) (Right 2)
```Right 2
```
````>>> ````Right 42 ^._left :: String
```""
```
````>>> ````Left "hello" ^._left
```"hello"
```

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

````>>> ````5^.remit _left
```Left 5
```

_right :: Prism (Either c a) (Either c b) a bSource

This prism provides a traversal for tweaking the right-hand value of an `Either`:

````>>> ````over _right (+1) (Left 2)
```Left 2
```
````>>> ````over _right (+1) (Right 2)
```Right 3
```
````>>> ````Right "hello" ^._right
```"hello"
```
````>>> ````Left "hello" ^._right :: [Double]
```[]
```

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

````>>> ````5^.remit _right
```Right 5
```

(Unfortunately the instance for `Traversable (Either c)` is still missing from base, so this can't just be `traverse`.)

_just :: Prism (Maybe a) (Maybe b) a bSource

This prism provides a traversal for tweaking the target of the value of `Just` in a `Maybe`.

````>>> ````over _just (+1) (Just 2)
```Just 3
```

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

````>>> ````5^.remit _just
```Just 5
```

# Simple

type SimplePrism s a = Prism s s a aSource

A `Simple Prism`.