## Applicative Arithmetic

# Safer Arithmetic

There are a couple partial functions in the Haskell Prelude which people seem to agree shouldn’t be there. `head`

, for example, will throw an error on an empty list. Most seem to agree that it should work something more like this:

```
head :: Foldable f => f a -> Maybe a
head = foldr (const . Just) Nothing
```

There are other examples, like `last`

, `!!`

, etc.

One which people *don’t* agree on, however, is division by zero. In the current Prelude, the following will throw an error:

`1 / 0`

The “safe” version might have a signature like this:

`(/) :: Fractional a => a -> a -> Maybe a`

However, this turns out to be quite a headache for writing code generally. So the default is the (somewhat) unsafe version.

Is there a way to introduce a safer version without much overhead, so the programmer is given the option? Of course! With some newtype magic, it’s pretty simple to write a wrapper which catches division by zero in some arbitrary monad:

```
newtype AppNum f a = AppNum
runAppNum :: f a
{deriving (Functor,Applicative,Monad,Alternative,Show,Eq,MonadFail)
}
instance (Num a, Applicative f) =>
Num (AppNum f a) where
abs = fmap abs
signum = fmap signum
+) = liftA2 (+)
(*) = liftA2 (*)
(-) = liftA2 (-)
(negate = fmap negate
fromInteger = pure . fromInteger
instance (Fractional a, MonadFail f, Eq a) =>
Fractional (AppNum f a) where
fromRational = pure . fromRational
/ ys =
xs >>=
ys case
\0 -> fail "divide by zero"
-> fmap (/ y) xs y
```

I’m using the `-XLambdaCase`

extension and `MonadFail`

here.

# Free Applicatives

You’ll notice that you only need `Applicative`

for most of the arithmetic operations above. In fact, you only need `Monad`

when you want to examine the contents of `f`

. Using that fact, we can manipulate expression trees using the free applicative from the free package. Say, for instance, we want to have free variables in our expressions. Using `Either`

, it’s pretty easy:

```
type WithVars = AppNum (Ap (Either String)) Integer
var :: String -> WithVars
= AppNum . liftAp . Left var
```

We can collect the free variables from an expression:

```
vars :: WithVars -> [String]
= runAp_ (either pure (const [])) . runAppNum
vars
= 1 :: WithVars
x = var "y"
y = var "z"
z
+ y + z) -- ["y","z"] vars (x
```

If we want to sub in, though, we’re going to run into a problem: we can’t just pass in a `Map String Integer`

because you’re able to construct values like this:

```
bad :: AppNum (Ap (Either String)) (Integer -> Integer -> Integer)
= AppNum (liftAp (Left "oh noes")) bad
```

We’d need to pass in a `Map String (Integer -> Integer -> Integer)`

as well; in fact you’d need a map for every possible type. Which isn’t feasible.

# GADTs

Luckily, we *can* constrain the types of variables in our expression so that they’re always `Integer`

, using a GADT:

```
data Variable a where
Constant :: a -> Variable a
Variable :: String -> Variable Integer
```

The type above seems useless on its own: it doesn’t have a `Functor`

instance, never mind an `Applicative`

, so how can it fit into `AppNum`

?

The magic comes from the free applicative, which converts any type of kind `Type -> Type`

into an applicative. With that in mind, we can change around the previous code:

```
type WithVars = AppNum (Ap Variable) Integer
var :: String -> WithVars
= AppNum . liftAp . Variable
var
vars :: WithVars -> [String]
= runAp_ f . runAppNum
vars where
f :: Variable a -> [String]
Constant _) = []
f (Variable s) = [s] f (
```

And write the function to sub in for us:

```
variableA :: Applicative f
=> (String -> f Integer) -> Variable a -> f a
Constant x) = pure x
variableA _ (Variable s) = f s
variableA f (
variable :: (String -> Integer) -> Variable a -> a
Constant x) = x
variable _ (Variable s) = f s
variable f (
replace :: Map String Integer -> WithVars -> Integer
= runAp (variable (m Map.!)) . runAppNum
replace m
"z",2), ("y",3)]) (x + y + z)
replace (Map.fromList [(-- 6
```

# Accumulation

This will fail if a free variable isn’t present in the map, unfortunately. To fix it, we *could* use `Either`

instead of `Identity`

:

```
replace :: Map String Integer -> WithVars -> Either String Integer
=
replace m
runAp$
(variableA ->
\s maybe (Left s) Right (Map.lookup s m)) .
runAppNum
```

But this only gives us the first missing variable encountered. We’d like to get back *all* of the missing variables, ideally: accumulating the `Left`

s. `Either`

doesn’t accumulate values, as if it did it would break the monad laws.

There’s no issue with the *applicative* laws, though, which is why the validation package provides a *non-monadic* either-like type, which we can use here.

```
replace :: Map String Integer -> WithVars -> AccValidation [String] Integer
=
replace m
runAp$
(variableA ->
\s maybe (AccFailure [s]) pure (Map.lookup s m)) .
runAppNum
+ y + z)
replace (Map.fromList []) (x -- AccFailure ["y","z"]
```

# Other uses

There are a bunch more applicatives you could use instead of `Either`

. Using lists, for instance, you could calculate the possible outcomes from a range of inputs:

```
range :: WithVars -> [Integer]
range = runAp (variable (const [1..3])) . runAppNum
range (x + y + z)
-- [3,4,5,4,5,6,5,6,7]
```

Or you could ask the user for input:

```
query :: WithVars -> IO Integer
= runAp (variable f) . runAppNum
query where
= do
f s putStr "Input a value for "
putStrLn s
fmap read getLine
```

Finally, and this one’s a bit exotic, you could examine every variable in turn, with defaults for the others:

```
zygo :: (forall x. f x -> x)
-> (forall x. f x -> (x -> a) -> b)
-> Ap f a
-> [b]
l :: forall x. f x -> x) (c :: forall x. f x -> (x -> a) -> b) =
zygo (fst . go id
where
go :: forall c. (c -> a) -> Ap f c -> ([b], c)
Pure x) = ([], x)
go _ (Ap x f) = (c x (k . ls) : xs, ls lx)
go k (where
= go (k . ($ lx)) f
(xs,ls) = l x
lx
examineEach :: WithVars -> [Integer -> Integer]
= zygo (variable (const 1)) g . runAppNum
examineEach where
g :: Variable a -> (a -> b) -> Integer -> b
Constant x) rhs _ = rhs x
g (Variable _) rhs i = rhs i g (
```

This produces a list of functions which are equivalent to subbing in for each variable with the rest set to 1.