# Calculator

Here we will build a simple calculator, following pioneers of the space Luite Stegemann, Ryan Trinkle, and Ivan Perez.

## Hello World

Let’s get a basic "Hello World" app up (this is provided if you are building a snowman). Luckily that is not too hard (but not too easy either):

``````main :: IO ()
main = runJSorWarp 8080 \$ (1)
simple (2)
runParDiff (3)
() (4)
(const "hello world") (5)
getBody (6)``````
 1 This is a little function to abstract over starting the application with GHC or GHCjs. If built with GHC it will run a server on port `8080`, if built with GHCjs it will just start the application as a normal JavaScript file. 2 This is the highest-level wrapper around the `shpadoinkle` function provided in core. It prevents you from doing the work of choosing a `Monad` to run event handlers (defaulting to `JSM`), and creating a territory (defaulting to a `TVar`). 3 We are using the ParDiff backend. No matter how simple the app, you must still choose a backend explicitly. 4 The initial state. Because this is a "hello world" example, it’s just `()`. 5 This is our view. Because we don’t care about the `()` we’re using `const` here. `"hello world"` is an `OverloadedString` of type `Html m a`. 6 This is what DOM node on the page will hold our application. We use `getBody` to get the `document.body` for the page.
 You need to stop ghcid and restart it after making any changes to the .cabal file.

Now that we have our hello world, let’s add some interactivity and perform addition on the part of the user:

To start, we will need a simple single number input:

``````num :: Int -> Html m Int
num x = input'
[ value . pack \$ show x (1)
, onInput (fromMaybe 0 . readMay . unpack) (2)
]``````
 1 Set the value of the input to the current state of the application. 2 When an `"input"` event occurs, update the state with the provided function.

Now we can use our single number input in our view to add up two numbers for our user.

``````view :: (Int, Int) -> Html m (Int, Int)
view (l,r) = (1)
div_
[ liftC (,r) fst \$ num l (2)
, " + "
, liftC (l,) snd \$ num r (3)
, text \$ " = " <> pack (show \$ l + r) (4)
]``````
 1 For now we can just use a tuple to house our two numbers. 2 We use the `num` component, rendering it with `l`. 3 We use the `num` component, rendering it with `r`. 4 We display the result of `l + r` to the user.
 Heterogeneous Composition We are using `liftC` and a `TupleSection` here to compose our `num` component. This is because `Html Int` and `Html (Int, Int)` obviously do not unify. `liftC` comes from the `Continuous` type class, which underpins event handling in Shpadoinkle. ``liftC :: (Functor m, Continuous f) => (a -> b -> b) -> (b -> a) -> f m a -> f m b`` To lift `Html Int` to `Html (Int,Int)` we need to provide `liftC` with both a getter function and a setter function.

## Selectable Operations

Now that we have some inputs that can perform addition, let the user select common operations. We start by making a new ADT:

``````data Operation
| Subtraction
| Multiplication
| Division
deriving (Eq, Show, Read, Enum, Bounded)``````

We will need some functions to get human readable display, as well as mapping to functions:

``````opFunction :: Operation -> (Int -> Int -> Int)
opText :: Operation -> Text``````

We will use a traditional Html `<select>` element to let the user pick the operation.

``````opSelect :: Html m Operation
opSelect = select [ onOption \$ read . unpack ] (1)
\$ opOption <\$> [ minBound .. maxBound ]
where
opOption o = option
[ value . pack \$ show o ] (2)
[ text \$ opText o ]``````
 1 When the select element changes, we `read` the value and use that as the model. 2 Values are just the operation applied to `show`, so it matches when we `read`.

Great! Now we have three members of our model, and so it’s time for an actual data type.

``````data Model = Model
{ operation :: Operation
, left      :: Int
, right     :: Int
} deriving (Eq, Show)``````

We will use the same technique with `liftC` to compose these components together:

``````view :: Model -> Html Model
view model = div_
[ liftC (\l m -> m { left      = l }) left      \$ num (left model)
, liftC (\o m -> m { operation = o }) operation \$ opSelect
, liftC (\r m -> m { right     = r }) right     \$ num (right model)
, text \$ " = " <> pack (show \$ opFunction
(operation model) (left model) (right model))
]``````

That’s it! The user can select an operation, enter two numbers, and see a result rendered.

Now if you are looking at the above code and starting to twitch because you are an optics fiend, that is the right instinct.

You can see the final code here running below:

Next we emulate a real-world immediate execution calculator in part 3.