Page 1

Page 2

# Arithmetic Expressions

## Remember this from the Arithmetic Quiz?

• ```data Expr = Num Integer
| Add Expr Expr
| Mul Expr Expr```
• ```eval :: Expr -> Integer
eval (Num n) = n
eval (Add a b) = eval a + eval b
eval (Mul a b) = eval a * eval b```
Page 3

# Symbolic Expressions

## How about expressions with variables in them?

```data Expr = Num Integer
| Var Name       -- new
| Add Expr Expr
| Mul Expr Expr

type Name = String```
Page 4

# Gathering variables

• Example: compute the list of variable names that occur in an expression
• ```vars :: Expr -> [Name]
vars (Num n) = []
vars (Var x) = [x]
vars (Add a b) = vars a `union` vars b
vars (Mul a b) = vars a `union` vars b```
• We use
`union`
(from `Data.List`) instead of
`++`
to avoid duplicated variable names in the result.
Page 5

# Evaluating Symbolic Expressions

• ```eval :: [(Name,Integer)] -> Expr -> Integer
eval env (Num n) = n
eval env (Var x) = fromJust (lookup x env)
eval env (Add a b) = eval env a + eval env b
eval env (Mul a b) = eval env a * eval env b```
• Where we used
• ```lookup   :: Eq key => [(key,value)] -> key -> Maybe value
fromJust :: Maybe a -> a```
• Using
`fromJust`
means we let the function crash if it encounteres an unknown variable.
• Doing it this way is a quick hack. We will see a better solution later.
Page 6

# The Maybe type

• `data Maybe a = Nothing | Just a`
• Useful for functions like
`lookup`
that need to indicate success or failure.
• ```lookup   :: Eq key => [(key,value)] -> key -> Maybe value
lookup k [] = Nothing
lookup k ((k',v):kvs) | k' == k   = Just v
| otherwise = lookup k kvs```
Page 7

# Symbolic Differentiation

Page 8
##### Symbolic Differentiation
• ```diff :: Expr -> Name -> Expr
diff (Num n)   x = Num 0
diff (Var y)   x = if y==x then Num 1 else Num 0
diff (Add a b) x = Add (diff a x) (diff b x)
diff (Mul a b) x = Add (Mul a (diff b x)) (Mul (diff a x) b)
```
• `diff ((Mul 2) (Var "x")) "x"` 2*1+0*x
• It works, but the resulting expressions need to be simplified!
Page 9

# Smart constructors

• We want to avoid creating expressions
`0+e`
,
`e+0`
,
`0*e`
,
`e*0`
,
`1*e`
,
`e*1`
...
• We can achieve this by using
`add`
and
`mul`
everywhere instead of
`Add`
and
`Mul`
• ```add (Num 0) b = b
add a (Num 0) = a
add a b = Add a b```
• ```mul (Num 0) b = Num 0
mul a (Num 0) = Num 0
mul (Num 1) b = b
mul a (Num 1) = a
mul a b = Mul a b```
• This helps a lot but more simplifications are needed...
Page 10

# Simplifying expressions

• We can add more rules in the smart constructors and make them even smarter, but...
• A more systematic approach to might be better.
• See the self-study exercises for Week 5!
Page 11

# Monadic Expression Evaluation

• The first version of eval again:
• ```eval :: Expr -> Integer
eval (Num n)     = n
eval (Add e1 e2) = eval e1 + eval e2
eval (Mul e1 e2) = eval e1 * eval e2```
• We can rewrite it using functions from the
`Applicative`
class
• ```evalA (Num n)   = pure n
evalA (Add a b) = pure (+) <*> evalA a <*> evalA b
evalA (Mul a b) = pure (*) <*> evalA a <*> evalA b```
• What is the type
`evalA`
?
Page 12
##### Monadic Expression Evaluation
• `evalA :: Applicative f => Expr -> f Integer`
• It works for any type in the
`Applicative`
class!
• It also works for any type in the
`Monad`
class (it's a subclass).
• Example:
`Maybe`
is in the
`Applicative`
class, so we can get
• `evalA :: Expr -> Maybe Integer`
Page 13

# Avoiding division by zero

• ```data Expr = -- ... Num, Add, and Mul as before ...
Div Expr Expr

evalD :: Expr -> Maybe Integer
evalD (Num n)   = pure n
evalD (Add a b) = pure (+) <*> evalD a <*> evalD b
evalD (Mul a b) = pure (+) <*> evalD a <*> evalD b
evalD (Div a b) = do x <- evalD a
y <- evalD b
safeDiv x y

safeDiv :: Integer -> Integer -> Maybe Integer
safeDiv x 0 = Nothing
safeDiv x y = Just (x `div` y)
```
• `safeDiv` doesn't quite fit with
`<*>`
or
`=<<`
, so I used the
`do`
notation.
Page 14

# Looking up variables

• Any function type
`(e->)`
is in
`Applicative`
, so we can pass extra arguments.
• We can make the environment implicit.
• ```evalE :: Expr -> [(Name, Integer)] -> Integer
evalE (Num n)   = pure n
evalE (Var x)   = fromJust . lookup x
evalE (Add a b) = pure (+) <*> evalE a <*> evalE b
evalE (Mul a b) = pure (*) <*> evalE a <*> evalE b```
Page 15

# Combining effects?

• We made two separate extensions of
`evalA`
:
• ```evalD :: Expr -> Maybe Integer
evalE :: Expr -> [(Name, Integer)] -> Integer```
• Can we combine them into this?
• `evalM :: Expr -> [(Name, Integer)] -> Maybe Integer`
• Or, if we give our monad a name:
• ```type Eval a = [(Name, Integer)] -> Maybe a

evalM :: Expr -> Eval Integer```
• But is
`Eval`
an instance of
`Monad`
?
• Unfortunately not!
Page 16

# A monad for eval

• We need to define a new type if we want to combine effects (or look for types in the libraries)
• ```data Eval a = E ([(Name,Integer)] -> Maybe a)
runE (E f) = f

instance Functor Eval where
fmap = liftM

instance Applicative Eval where
pure = return
(<*>) = ap

instance Monad Eval where
return x = E (\ _ ->return x)
E m >>= f = E (\env -> do a <- m env; runE (f a) env)

divByZero = E (\ _ -> Nothing)
lookupVar x = E (lookup x)
```
Page 17

# Combining effects

## The finished monadic evaluator

```evalM :: Expr -> Eval Integer
evalM (Num n) = pure n
evalM (Var x) = lookupVar x
evalM (Add a b) = (+) <\$> evalM a <*> evalM b
evalM (Mul a b) = (*) <\$> evalM a <*> evalM b
evalM (Div a b) = do x <- evalM a
y <- evalM b
safeDiv x y

safeDiv x 0 = divByZero
safeDiv x y = pure (x `div` y)
```
Page 18

# Final thoughts on the monadic evaluator

• In examples small enough to fit on a slide, using monads like this is probably overkill.
• The benefits show up when the code gets larger and you can add more effects to the monad without rewriting all of the code that uses it.
• By using
`Either`
instead of
`Maybe`
we could return informative error messages ("division by zero" or "undefined variable") instead of
`Nothing`
.
• It only takes a few simple changes in the monad, the function
`evalM`
remains unchanged!