## Record Syntax, Lenses and Prisms: Part 3 - Prisms

September 7, 2014

## Prisms

### So what are prisms?

Prisms are like lenses just for sum types … - the most memorable sentence, but I don’t think very helpful at first glance.

``````
> data Town = Prague | Vienna | Kingston | London | Hipsterhausen deriving (Show, Eq)

> data Pirate = Captain   { _attributes :: Human, _ship :: String}
>             | FirstMate { _attributes :: Human, _shanty :: String}
>             | Marauder  { _attributes :: Human, _hometown :: Town}

> makeLenses ''Human
> makeLenses ''Body
> makeLenses ''Pirate``````

Pirate is a sum type - with different records in each constructor.

## A tangent on sums and products

### Sums

Why is the above called a sum type, just let us calculate the number of options we have in a sum type:

``````
data Sum = One | Two | Three``````

If I have a variable `x :: Sum` it has exactly three values it can be

• `x = One`
• `x = Two`
• `x = Three`

so the sum of the number of constructors is the solution of how many options `x` can be.

### Product

So how come product types to their names - you might already guess it.

``````
data Product = P Sum Sum``````

For a variable `y :: Product` we find `y` can be `|Sum|×|Sum|` many possible values:

• `y = P One One`
• `y = P One Two`
• `y = P One Three`
• `y = P Two One`
• `y = P Two Two`
• `y = P Two Three`
• `y = P Three One`
• `y = P Three Two`
• `y = P Three Three`

### So can anybody find what exponential types are?

``````
data Two = One | Two
data THREE = ONE | TWO | THREE``````

So the functions from `Two -> THREE` have exactly `|Two|^|THREE|` many elements.

``````
one,two,three,four,five,six,seven,eight :: Two -> THREE
one   One = ONE
one   Two = ONE
two   One = TWO
two   Two = TWO
three One = THREE
three Two = THREE
four  One = ONE
four  Two = TWO
five  One = ONE
five  Two = THREE
six   One = TWO
six   Two = THREE
seven One = THREE
seven Two = ONE
eight One = THREE
eight Two = TWO``````

## Back to Prisms

The problem with lenses is that `cpt` some getters don’t make sense. For datatypes that have a special elements, so called monoids like `String` with `""` we get special getters, but for `Town` for example …

``````
Prelude > cpt^.shanty
""
Prelude > cpt^.hometown
...
error message complaining about Town not being a monoid
...``````

So an easy way to get special elements is combining it with `Maybe`. And that’s what prisms are - getters with `Maybe`-values instead of errors.

So how do we get them - again as with prisms we (have to) build them with template haskell magic using

``````
> makePrisms ''Human
> makePrisms ''Body
> makePrisms ''Pirate``````

This magic words create “Constructors” `_Captain`, `_FirstMate` and `_Marauder` and the lens library provides functions `preview`, `review` and `^?`.

Now what are those functions doing - they select one branch in a sum type.

``````
Prelude > preview _Captain cpt
Just (Attributes {...},"SS Sea Serpent")
Prelude > preview _Captain mrd
Nothing``````

But there is also an infix shortcut for `preview` - `(^?)` so we could have written the above `cpt^._Captain` or use it with accessor-like functions as `hometown`,`ship`,`shanty` or `attributes`.

``````
Prelude > cpt^?hometown
Nothing
Prelude > cpt^?ship
Just "SS Sea Serpent"
Prelude > mrd^?hometown
Just Hipsterhausen``````

### So what about `review`?

The `review` function can create new things from the results of `preview`, well not exactly but almost and with use of `(<\$>)` from `Control.Applicative` we can make them work together

``````
Prelude> :t preview _Captain cpt
preview _Captain cpt :: Maybe (Human, String)
Prelude> let Just x = preview _Captain cpt
Prelude> :t review _Captain x
review _Captain x :: Pirate
Prelude> :t review _Captain <\$> preview _Captain cpt
review _Captain <\$> preview _Captain cpt :: Maybe Pirate
Prelude> review _Captain <\$> preview _Captain cpt
Just Captain {Attributes {...},"SS Sea Serpent"}
Prelude> review _Captain <\$> preview _Captain mrd
Nothing
Prelude> review _Captain <\$> preview _Marauder mrd
... Error ... -- Captain needs String (ship name) where Marauder has a Town as
a second argument``````

So Prisms do not fix everything - but provide a safety layer for simple accessing stuff and sometimes for generating stuff as well.

So thats all I know about Lenses and Prisms - for understanding the type signatures - I still do not feel confident to present about.