Download as pdf or txt
Download as pdf or txt
You are on page 1of 2

Prof. Dr.

Ralf Hinze TU Kaiserslautern


M.Sc. Sebastian Schloßer
Fachbereich Informatik
AG Programmiersprachen

Functional Programming: Exercise 9


Sheet published: Friday, July 1st
Exercise session: Thursday, July 7th, 12:00

Exercise 9.1 (Skeleton: Evaluator.hs). The goal of this exercise is to extend our eval-
uator from last week such that we can evaluate expressions like x=3; y=4; x+y.
We use the following data type for representing such expressions in Haskell:
type Id = String
data Expr a
= Lit a — a literal
| Expr a :+: Expr a — addition
| Expr a :−: Expr a — subtraction
| Expr a :∗: Expr a — multiplication
| Expr a :/: Expr a — division
| Expr a :#: Expr a — sequencing (;)
| Id :=: Expr a — variable assignment
| Var Id — variable access
Compared to last week, there are some differences:
• The type is now parametric such that we are no longer limited to Integer numbers.
However, all number literals appearing in an expression must be of the same type.
• There are additional arithmetic operations.
• The expression "x" :=: e assigns the result of the expression e to the variable x.
Since the assignment itself is an expression as well, it must also return a result,
which should be the result of e. This way, we can assign multiple variables at once:
"x" :=: "y" :=: Lit 4 sets both x and y to 4, and evaluates to 4.
• The expression Var "x" evaluates to the value that has been previously assigned to
the variable x. If x has not yet been assigned, we just assume it has the value 0.
• The expression e1 :#: e2 is a sequence, much like the >> operator for monads or
the semicolon in imperative languages. It evaluates e1 solely for its side-effects
(e.g. assignments) and then e2 is evaluated and its result returned.
Note that the template file comes with a parser:
parse :: Num a ⇒ String → Maybe (Expr a)
So you can easily create expressions in the interpreter:
iiii parse "4+5+6"
Just ((Lit 4 :+: Lit 5) :+: Lit 6)
iiii parse "x=3; y=4; x+y"
Just ("x" :=: Lit 3 :#: ("y" :=: Lit 4 :#: Var "x" :+: Var "y"))
iiii parse "x=y=4.2; x + y" :: Maybe (Expr Float)
Just ("x" :=: ("y" :=: Lit 4.2) :#: Var "x" :+: Var "y")

1
a) The variables in our expressions are updateable state. We will handle those using the
state monad:

newtype State s a = State (s → (a, s))

Provide Monad , Applicative and Functor instance for State s. You only need to define
>= since fmap and h∗i can be derived and return defaults to pure.
pure and >
Additionally, you should provide

get :: State s s
put :: s → State s ()

for reading and writing the state.


In case you get stuck, you can read through the wikibook article on the state monad1 .
It has many examples and explanations, but also the solution to this task (you should
of course try it yoursef first). As noted in the template file, you could actually omit
this task altogether and just import the state monad from the standard library (which
is what you would do in a real-world scenario).
b) Extend our previous evaluater to support [(Id , a)] as state. The list contains pairs of
variable name and the value bound to that variable.

evaluate :: Integral a ⇒ Expr a → State [(Id , a)] a

We choce Integral instead of Num because it allows us to use the div function. Note
that we cannot handle division by zero in a graceful way yet, because the Monad only
supports state. So our evaluator will throw an exception if a division by zero occurs.
We can copy most of the cases from our previous Applicative implementation. You
only need to implement sequencing, assignments, and variable access.
The template provides a helper function

eval :: Integral a ⇒ Expr a → (a, [(Id , a)])

that starts the evaluator with an empty initial state and returns a pair of result and
final state.
c) Play around whith the provided main IO action in the template file. When you compile
and run the program (or just type main into the interpreter), the program asks for an
expression (in the nice string representation above) and then parses and evaluates it.
d) Look at the parser which is provided in the template file. Revisit the parser combinators
chapter from the lecture and try to understand it with monads in mind.
e) Further extend the evaluator. Possible ideas:
• Error handling for division by zero and not initialized variables. You need to
combine State and Maybe.
• Non-determinism. Add a :?: operator to the Expr type, implement it and also
extend the parser to support it.

1
https://en.wikibooks.org/wiki/Haskell/Understanding_monads/State

You might also like