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

Prof. Dr.

Ralf Hinze TU Kaiserslautern


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

Functional Programming: Exercise 6


Sheet published: Friday, June 10th
Exercise session: Thursday, June 23rd, 12:00

Exercise 6.1 (Skeleton: LazyNaturals.hs). The goal of this exercise is to develop a


datatype for lazy numeric computations. Normally, if a numeric expression is evaluated
at all, it must be evaluated completely. For example, the comparison length xs > 0 forces
evaluation of the entire list xs.
We introduce a new numeric datatype that supports natural numbers only. It represents
numbers using partitions i + j + . . . where the component values i, j, . . . are positive whole
numbers, i.e. i > 0, j > 0, . . . . We call these stuctures super-naturals:

infixr 6 :+
data Super natural = O | !natural :+ Super natural

A super-natural is either zero, represented by O, or of the form p :+ ps where p is


an evaluated part but ps may be unevaluated. The exclamation mark is a strictness
annotation, forcing the first argument of :+ to be fully evaluated. The second argument
still is evaluated lazily. The type parameter natural can be any numeric type, e.g. Integer .
Using super-naturals, the evaluation of length xs > O only needs the outermost con-
structor resulting from length xs to decide whether O > O = False or p :+ ps > O = True
applies (remember that p > 0 holds due to our invariant).

a) Implement a function

value :: Num natural ⇒ Super natural → natural

that reduces a super-natural to its natural value.


Example: value (1 :+ 3 :+ 5 :+ 1 :+ 4 :+ 2 :+ 1 :+ O) = 17

value O =0
value (p :+ ps) = p + value ps

1
b) Implement functions

width :: Num natural ⇒ Super natural → natural


height :: (Num natural , Ord natural ) ⇒ Super natural → natural

computing the number of entries (width) and the largest entry (height) in the partition.
Example:

width (1 :+ 3 :+ 5 :+ 1 :+ 4 :+ 2 :+ 1 :+ O) = 7
height (1 :+ 3 :+ 5 :+ 1 :+ 4 :+ 2 :+ 1 :+ O) = 5

width O =0
width ( :+ ps) = 1 + width ps
height O =0
height (p :+ ps) = max p (height ps)

2
c) Implement addition and multiplication for super-naturals:

(+) :: Num natural ⇒ Super natural → Super natural → Super natural


(∗) :: Num natural ⇒ Super natural → Super natural → Super natural

Try to find a good balance between the width of the result and lazyness of the compu-
tation: The result should not be wider than the widest argument. Only when the kth
part of a result is demanded any kth part of an argument should be evaluated.
Make sure to maintain the invariant that the partitions contain positive numbers
only.

For addition, we zip both super-naturals together, using addition on the natural
number type. That approach gives width (x + y) = max (width x ) (width y) and
height (x + y) 6 height x + height y. Evaluation is demand-driven (lazy).

O + qs = qs
ps +O = ps
(p :+ ps) + (q :+ qs) = (p + q) :+ (ps + qs)

For multiplication, a good solution is not that straight-forward:

(a + b + c) · (d + e + f ) = a · d + a · e + a · f + b · d + b · e + b · f + c · d + c · e + c · f

Since we do not want to have width (x ∗ y) = width x ∗ width y, we need to combine


some computations in each step without a complete eagerly evaluation of one of the
inputs. The idea is to group the result as

(a · d) + (a · e + b · d + b · e) + (a · f + b · f + c · d + c · e + c · f )

such that the first group only needs the first part of each input, the second group
only needs to process the inputs up to the second part, and so on.

O ∗ =O
∗O =O
(p :+ ps) ∗ (q :+ qs) = (p ∗ q) :+ (mult q ps + mult p qs + ps ∗ qs) where
mult :: Num natural ⇒ natural → Super natural → Super natural
mult O =O
mult n (m :+ ms) = n ∗ m :+ mult n ms

Note that mult multiplies a natural with a super-natural. That approach again gives
width (x + y) = max (width x ) (width y), with one exception: the width is 0 if either
of the inputs is O.

3
d) Implement comparison for super-naturals:

compare :: (Num natural , Ord natural ) ⇒ Super natural → Super natural → Ordering

It is easy to see that for evaluating comparison, we need to evaluate at least one of the
inputs completely. An easy implementation that completely evaluates both inputs
would be compare n m = compare (value n) (value m). But this is non-optimal
if one super-natural has a much longer width than the other, e.g. for x > 5 :+ O
where x is the result of a compution yielding a wide super-natural.

compare ps qs = c (0, ps) (0, qs) where


c :: (Num natural , Ord natural ) ⇒ (natural , Super natural ) → (natural , Super natural ) → Orderi
c (pn, ps) (qn, qs) = case compare pn qn of
LT → case ps of
O → LT
(p :+ ps) → c (pn + p, ps) (qn, qs)
GT → case qs of
O → GT
(q :+ qs) → c (pn, ps) (qn + q, qs)
EQ → case (ps, qs) of
(O, O) → EQ
( :+ , O) → GT
(O, :+ ) → LT
(p :+ ps, q :+ qs) → c (p, ps) (q, qs)

The c helper function has an accumulating natural parameter for each input, sum-
ming up the part of the super-natural that has already been consumed. The function
recursively consumes only the super-natural that has been smaller up to now, until
the smaller one reaches its end.
The evaluation is lazy and non-strict, see for example 4:+⊥<3:+O and 3:+O <4:+⊥.

e) Why is the restriction to partitions of positive whole numbers important for your
implementation?

With negative numbers, we cannot determine the result of compare without com-
pletely evaluating both inputs.

You might also like