What if I told you that a spreadsheet could be a library instead of an application? What would that even mean? How do we distill the logic behind spreadsheets into a reusable abstraction? My `mvc-updates`

library answers this question by bringing spreadsheet-like programming to Haskell using an intuitive `Applicative`

interface.

The central abstraction is an `Applicative`

`Updatable`

value, which is just a `Fold`

sitting in front of a `Managed`

`Controller`

:

```
data Updatable a =
forall e . On (Fold e a) (Managed (Controller e))
```

The `Managed`

`Controller`

originates from my `mvc`

library and represents a resource-managed, concurrent source of values of type `e`

. Using `Monoid`

operations, you can interleave these concurrent resources together while simultaneously merging their resource management logic.

The `Fold`

type originates from my `foldl`

library and represents a reified left fold. Using `Applicative`

operations, you can combine multiple folds together in such a way that they still pass over the data set just once without leaking space.

To build an `Updatable`

value, just pair up a `Fold`

with a `Managed`

`Controller`

:

```
import Control.Foldl (last, length)
import MVC
import MVC.Updates
import MVC.Prelude (stdinLines, tick)
import Prelude hiding (last, length)
-- Store the last line from standard input
lastLine :: Updatable (Maybe String)
lastLine = On last stdinLines
-- Increment every second
seconds :: Updatable Int
seconds = On length (tick 1.0)
```

What's amazing is that when you stick a `Fold`

in front of a `Controller`

, you get a new `Applicative`

. This `Applicative`

instance lets you combine multiple `Updatable`

values into new derived `Updatable`

values. For example, we can combine `lastLine`

and `seconds`

into a single data type that tracks updates to both values:

```
import Control.Applicative ((<$>), (<*>))
data Example = Example (Maybe String) Int deriving (Show)
example :: Updatable Example
example = Example <$> lastLine <*> seconds
```

`example`

will update every time `lastLine`

or `seconds`

updates, caching and reusing portions that do not update. For example, if `lastLine`

updates then only the first field of `Example`

will change. Similarly, if `seconds`

updates then only the second field of `Example`

will change.

When we're done combining `Updatable`

values we can plug them into `mvc`

using the `updates`

function:

`updates :: Buffer a -> Updatable a -> Managed (Controller a)`

This gives us back a `Managed`

`Controller`

we can feed into our `mvc`

application:

```
viewController :: Managed (View Example, Controller Example)
viewController = do
controller <- updates Unbounded example
return (asSink print, controller)
model :: Model () Example Example
model = asPipe $
Pipes.takeWhile (\(Example str _) -> str /= Just "quit")
main :: IO ()
main = runMVC () model viewController
```

This program updates in response to two concurrent inputs: time and standard input.

```
$ ./example
Example Nothing 0
Test<Enter>
Example (Just "Test") 0 <-- Update: New input
Example (Just "Test") 1 <-- Update: 1 second passed
Example (Just "Test") 2 <-- Update: 1 second passed
ABC<Enter>
Example (Just "ABC") 2 <-- Update: New input
Example (Just "ABC") 3 <-- Update: 1 second
quit<Enter>
$
```

#### Spreadsheets

The previous example was a bit contrived, so let's step it up a notch. What better way to demonstrate spreadsheet-like programming than .. a spreadsheet!

I'll use Haskell's `gtk`

library to set up the initial API, which consists of a single exported function:

```
module Spreadsheet (spreadsheet) where
spreadsheet
:: Managed -- GTK setup
( Updatable Double -- Create input cell
, Managed (View Double) -- Create output cell
, IO () -- Start spreadsheet
)
spreadsheet = ???
```

You can find the full source code here.

Using `spreadsheet`

, I can now easily build my own spread sheet application:

```
{-# LANGUAGE TemplateHaskell #-}
import Control.Applicative (Applicative, (<$>), (<*>))
import Lens.Family.TH (makeLenses)
import MVC
import MVC.Updates (updates)
import Spreadsheet (spreadsheet)
-- Spreadsheet input (4 cells)
data In = I
{ _i1 :: Double
, _i2 :: Double
, _i3 :: Double
, _i4 :: Double
}
-- Spreadsheet output (4 cells)
data Out = O
{ _o1 :: Double
, _o2 :: Double
, _o3 :: Double
, _o4 :: Double
}
makeLenses ''Out
-- Spreadsheet logic that converts input to output
model :: Model () In Out
model = asPipe $ loop $ \(I i1 i2 i3 i4) -> do
return $ O (i1 + i2) (i2 * i3) (i3 - i4) (max i4 i1)
main :: IO ()
main = runMVC () model $ do
(inCell, outCell, go) <- spreadsheet
-- Assemble the four input cells
c <- updates Unbounded $
I <$> inCell <*> inCell <*> inCell <*> inCell
-- Assemble the four output cells
v <- fmap (handles o1) outCell
<> fmap (handles o2) outCell
<> fmap (handles o3) outCell
<> fmap (handles o4) outCell
-- Run the spread sheet
liftIO go
return (v, c)
```

You can install this program yourself by building my `mvc-updates-examples`

package on Github:

```
$ git clone https://github.com/Gabriel439/Haskell-MVC-Updates-Examples-Library.git
$ cd Haskell-MVC-Updates-Examples-Library
$ cabal install
$ ~/.cabal/bin/mvc-spreadsheet-example
```

Or you can watch this video of the spreadsheet in action:

The key feature I want to emphasize is how concise this spreadsheet API is. We provide our user an `Applicative`

input cell builder and a `Monoid`

output cell builder, and we're done. We don't have to explain to the user how to acquire resources, manage threads, or combine updates. The `Applicative`

instance for `Updatable`

handles all of those trivial details for them. Adding extra inputs or outputs is as simple as chaining additional `inCell`

and `outCell`

invocations.

#### Reactive animations

We don't have to limit ourselves to spread sheets, though. We can program `Updatable`

graphical scenes using these same principles. For example, let's animate a cloud that orbits around the user's mouse using the `sdl`

library. Just like before, we will begin from a concise interface:

```
-- Animation frames for the cloud
data Frame = Frame0 | Frame1 | Frame2 | Frame3
-- To draw a cloud we specify the frame and the coordinates
data Cloud = Cloud Frame Int Int
-- mouse coordinates
data Mouse = Mouse Int Int
sdl :: Managed -- SDL setup
( View Cloud -- Draw a cloud
, Updatable Mouse -- Updatable mouse coordinates
)
```

The full source is located here.

In this case, I want to combine the `Updatable`

mouse coordinates with an `Updatable`

time value:

```
main :: IO ()
main = runMVC () (asPipe cat) $ do
(cloudOut, mouse) <- sdl
let seconds = On length (tick (1 / 60))
toFrame n = case (n `div` 15) `rem` 4 of
0 -> Frame0
1 -> Frame1
2 -> Frame2
_ -> Frame3
cloudOrbit t (Mouse x y) = Cloud (toFrame t) x' y'
where
x' = x + truncate (100 * cos (fromIntegral t / 10))
y' = y + truncate (100 * sin (fromIntegral t / 10))
cloudIn <- updates Unbounded (cloudOrbit <$> seconds <*> mouse)
return (cloudOut, cloudIn)
```

`cloudOrbit`

is defined as a pure function from the current time and mouse coordinates to a `Cloud`

. With the power of `Applicative`

s we can lift this pure function over two `Updatable`

values (`mouse`

and `seconds`

) to create a new `Updatable`

`Cloud`

that we pass intact to our program's `View`

.

Like before, you can either run this program yourself:

```
$ git clone https://github.com/Gabriel439/Haskell-MVC-Updates-Examples-Library.git
$ cd Haskell-MVC-Updates-Examples-Library
$ cabal install
$ ~/.cabal/bin/mvc-spreadsheet-example
```

... or you can watch the video:

#### Under the hood

`mvc-updates`

distinguishes itself from similar libraries in other languages by not relying on a semantics for concurrency. The `Applicative`

instance for `Updatable`

uses no concurrent operations, whatsoever:

```
instance Applicative Updatable where
pure a = On (pure a) mempty
(On foldL mControllerL) <*> (On foldR mControllerR)
= On foldT mControllerT
where
foldT = onLeft foldL <*> onRight foldR
mControllerT = fmap (fmap Left ) mControllerL
<> fmap (fmap Right) mControllerR
onLeft (Fold step begin done) =
Fold step' begin done
where
step' x (Left a) = step x a
step' x _ = x
onRight (Fold step begin done) =
Fold step' begin done
where
step' x (Right a) = step x a
step' x _ = x
```

In fact, this `Applicative`

instance only assumes that the `Controller`

type is a `Monoid`

, so this trick generalizes to any source that forms a `Monoid`

.

This not only simplifies the proof of the `Applicative`

laws, but it also greatly improves efficiency. This `Applicative`

instance introduces no new threads or buffers. The only thread or buffer you will incur is in the final call to the `updates`

function, but expert users can eliminate even that overhead by inlining the logic of the `updates`

function directly into their `mvc`

program.

#### Lightweight

The `mvc-updates`

library is incredibly small. Here's the entire API:

```
data Updatable = forall e . On (Fold e a) (Controller e)
instance Functor Updatable
instance Applicative Updatable
updates :: Buffer a -> Updatable a -> Managed (Controller a)
```

The library is very straightforward to use:

- Build
`Updatable`

values - Combine them using their
`Applicative`

instance - Convert them back to a
`Managed`

`Controller`

when you're done

That's it!

The small size of the library is no accident. The `Updatable`

abstraction is an example of a scalable program architecture. When we combine `Updatable`

values together, the end result is a new `Updatable`

value. This keeps the API small since we always end up back where we started and we never need to introduce additional abstractions.

There is no need to distinguish between "primitive" `Updatable`

values or "derived" `Updatable`

values or "sheets" of `Updatable`

values. The `Applicative`

interface lets us unify these three concepts into a single uniform concept. Moreover, the `Applicative`

interface is one of Haskell's widely used type classes inspired by category theory, so we can reuse people's pre-existing intuition for how `Applicative`

s work. This is a common theme in Haskell where once you learn the core set of mathematical type classes they go a very, very long way.

#### Conclusion

Hopefully this post will get you excited about the power of `Applicative`

programming. If you would like to learn more about `Applicative`

s, I highly recommend the "Applicative Programming with Effects" paper by Conor McBride and Ross Paterson.

I would like to conclude by saying that there many classes of problems that the `mvc-updates`

library does **not** solve well, such as:

- build systems,
- programs with computationally expensive
`View`

s, and: `Updatable`

values that share state.

However, `mvc-updates`

excels at:

- data visualizations,
- control panels, and:
- spread sheets (of course).

You can find the `mvc-updates`

library up on Hackage or on Github.