# Immediate Execution

All the prior articles on writing a calculator in GHCjs feature old school functionality, namely immediate execution, which is a terrible UX. If you ever make an actual calculator app, at least let your users type into an input the expression they want evaluated. However, this choice makes good sense, as it requires a state machine and some other properties that make it good for learning.

This portion of the tutorial makes use of Lens in an effort to show how you might leverage optics in your applications.

## Digits

Let’s model out our calculator as types. We could easily just use `Char` or `Int` to represent our numbers, however this violates the principle of making illegal states unrepresentable. So instead we will use an ADT and marshal.

``````data Digit
= Seven | Eight | Nine
| Four  | Five  | Six
| One   | Two   | Three
| Zero deriving (Eq, Show, Ord, Enum, Bounded)``````

Next, before we can make buttons for the digits, we need a way marshal a `Digit` to its respective `Char`, which can be handled nicely by a Prism. We need it to be a Prism because not all `Char` s have a corresponding `Digit`.

``charDigit :: Prism' Char Digit``

Now that we can marshal between the Haskell representation and one we can show our user, we can make a button for digits:

``````digit :: Digit -> Html m Digit
digit d = button [ onClick \$ const d (1)
, className \$ "d" <> d' (2)
] [ text d' ]
where d' = d ^. re charDigit . to (pack . pure)``````
 1 When clicking the button, we send the corresponding digit 2 Add a class for styling later

## Entries

`Digit` gives us everything we need to represent our number pad, but it is not enough to represent a user inputed number. So we can make a simple type to represent an entry consisting of multiple digits.

``newtype Entry = Entry [Digit]``

This works so long as our calculator need only work with Natural numbers, however we want to do a bit more. We want to allow for decimals as well as negative numbers.

### Decimals

To allow for decimals, we need to have a distinction so when the user presses a digit on the number pad, we know whether to add it before or after the decimal. We also need to ensure that when the user presses btn:[.] we can move from one state to the other.

``data Entry = Whole [Digit] | [Digit] :<.> [Digit]``

With this we can implement the decimal interaction logic easily. When the user presses btn:[.] and we have a whole number, we transition to the `:<.>` constructor.

``````addDecimal :: Entry -> Entry
addDecimal = \case
Whole xs -> xs :<.> []
ys       -> ys``````

When the user presses a digit button and we have a whole number, we append the new digit to the end of the list. Otherwise, we append to the space after the decimal.

``````applyDigit :: Digit -> Entry -> Entry
applyDigit d = \case
Whole xs   -> Whole \$ xs <> [d]
xs :<.> ys -> xs :<.> (ys <> [d])``````

### Negative

To allow for negatives, we can just make the `Entry` type recursive.

``````data Entry = Whole [Digit]
| [Digit] :<.> [Digit]
| Negate Entry``````

By adding the `Negate` constructor we can represent negatives of any existing `Entry` in the system. This makes the logic for the btn:[-/+] button straight forward.

``````neg :: Entry -> Entry
neg = \case
Negate e -> e
e -> Negate e``````

### Show

Now to show the entry to our user in the calculator readout, we need to convert to a human readable version.

``````instance Show Entry where
show = let asChar = traverse . re charDigit in \case
Whole xs   -> xs ^.. asChar
xs :<.> ys -> xs ^.. asChar <> "." <> ys ^.. asChar
Negate e   -> '-' : show e``````

This shows instance results in an intuitive display for the user where each button press is reflected 1:1. (IE no trailing ".0" or other issues)

### Double

Lastly on the subject of entries, we need the ability to do math. To accomplish this we need to marshal entries to an actual number type (in this case `Double`), as well as marshal our results back to an `Entry`. We do this by creating an Iso.

``frac :: Iso' Entry Double``

This allows us to easily move in both directions.

 Outlaw The source version is not a lawful isomorphism, but this outlaw is harmless. Producing a lawful instance is left as an exercise for the reader.

## Operators

We need a representation of operators to allow our user to perform work. We can do this with another simple enumeration:

``````data Operator
= Addition
| Multiplication
| Subtraction
| Division
deriving (Eq, Enum, Bounded)``````

And as before we need to show this to our user:

``````instance Show Operator where
show = \case
Addition       -> "+"
Subtraction    -> "−"
Multiplication -> "×"
Division       -> "÷"

operate :: Maybe Operator -> Operator -> Html m Operator
operate active o = button
[ onClick (const o) (1)
, className ("active", Just o == active) (2)
] [ text . pack \$ show o ]``````
 1 When clicked, the button sends the corresponding operator 2 Set the `"active"` class if this button is the active button (for styling)

## Model

Now we can actually define our model. Ultimately, the immediate execution calculator is a state machine with two major states:

1. There is a current entry.

2. There is a current entry, and a previous entry, and an operation.

Input Readout Current Operation Entry

`[]`

`1`

`1`

``

`2`

`12`

`[1,2]`

`+`

`+`

`[]`

`+`

`[1,2]`

`4`

`+4`

``

`+`

`[1,2]`

`=`

`16`

`[1,6]`

One way to model this is with the following type:

``````data Operation = Operation
{ _operator :: Operator
, _previous :: Entry
} deriving (Eq, Show)

makeFieldsNoPrefix ''Operation

data Model = Model
{ _current   :: Entry (1)
, _operation :: Maybe Operation (2)
} deriving (Eq, Show)

makeFieldsNoPrefix ''Model``````
 1 We always have a current entry. 2 We might have a previous entry and an operation.

## Buttons

Now let’s start building the final view. The calculator needs a readout area that shows the user the current state of the system.

``readout :: Model -> Html m a``

Because the readout consumes the state but never produces an update we should leave the HTML parametric.

 The presence `a` in the above signature is proof that the HTML produced is non-interactive.

We also need our buttons. This calculator will have the following familiar buttons:

### All Clear

Resets the calculator to the `initial` state.

``````clear :: Html m Model
clear  = button [ class' "clear", onClick \$ const initial ] [ "AC" ]``````

### Negate

Negates the current entry. Phrased on the button as [-/+].

``````posNeg :: Html m Model
posNeg = button [ class' "posNeg", onClick (current %~ neg) ] [ "-/+" ]``````

### Numberpad

The nine digit pad (excluding 0).

``````numberpad :: Html m Digit
numberpad = H.div "numberpad"
. L.intercalate [ br'_ ] (3)
. L.chunksOf 3 (2)
\$ digit <\$> [minBound .. pred maxBound] (1)``````
 1 Get a list all members of our `Digit` type, excluding `Zero`. We are leveraging the derived `Ord` instance here, as the type definition already has the digits arranged for the number pad, with `Zero` as `maxBound`. 2 Split the resulting list of HTML into rows of three buttons each. (`chunksOf` is a part of `Data.List`) 3 Add between each row.

### Decimal

A button to apply adding a decimal point to the current entry.

``````dot :: Html m Model
dot = button [ onClick \$ current %~ addDecimal ] [ "." ]``````

### Arithmetic

Each operator button does the following: . Sets the operation to the given operator. . Sets the previous entry to be the current entry. . Blanks the current entry.

``````operations :: Model -> Html m Model
operations x = H.div "operate" \$ fmap (\o -> x
& operation .~ Just (Operation o (x ^. current))
& current   .~ noEntry) (3)
. operate (x ^? operation . traverse . operator) (2)
<\$> [minBound .. maxBound] (1)``````
 1 Leverage `Bounded` and `Enum` to get a list of operators. 2 Get the current operator if there is one (for display purposes). 3 Apply the update described above.

### Equals

Last we come to equals. This button should calculate the result of our operation, blank the operator and previous entry, and set the current entry to our result.

``````calcResult :: Model -> Model
calcResult x = x
& operation .~ Nothing
& current .~ case x ^. operation of
Nothing -> x ^. current
Just o ->
let l = o ^. previous . frac
r = x ^. current  . frac
in (^. from frac) \$ case o ^. operator of
Addition       -> l + r
Subtraction    -> l - r
Multiplication -> l * r
Division       -> if r == 0 then l else l / r``````

Based on the above examples, you should be able to see what is going on in this code. Writing a button to perform this operation is straightforward.

``````equals :: Html m Model
equals = button [ class' "equals", onClick calcResult ] [ "=" ]``````

## The View

Now, we can construct the final view by composing together our existing parts.

``````view :: Model -> Html Model
view x = H.div "calculator"
[ readout x
, H.div "buttons"
[ clear, posNeg, operations x
, numberpad
, H.div "zerodot"
[ digit Zero, dot, equals ]
]
]``````

And we are done.

## Conclusion

You can review the final code here, and see it running here.

 Simplicity There were no Monads, no message types, no FRP networking, no causality, and we never considered when or how components render. Instead we focused on data structures, and simple functions with simple types.

Thank you for your time.