# Conference: Week 5

• Check calendar for dates around Reading Period, Health Days, etc.

• Midterm:

• Up to but not including exception handling.
• Self-scheduled, to be taken between Wed. 4/7 (noon) and Saturday 4/10 (noon).
• 2-3 hours.
• HW-like questions.
• Possibly small code questions (ML, but no Lisp).
• Test basic thoughts, ideas, techniques. Not minutiae.

### 2. Type Inference

Infer the type for the following function use our type inference algorithm:

fun f(g,h) = g(h) + 2;

Solution

### 3. Folding Fun (Submit this one with your HW!)

Your GitLab account will have a “hw5” project for your to use for this question. You can follow the same instructions as on HW 1 for cloning it and adding a partner.

The “fold-left" (and”fold-right") functions appear in many languages (as reduceRight/Left in Javascript, as accumulate in C++, as foldl/foldr in ML, and so on.)

Here are their definitions in ML:

fun foldr f v nil =     v
| foldr f v (x::xs) = f (x, foldr f v xs);

fun foldl f v nil =     v
| foldl f v (x::xs) = foldl f (f(x, v)) xs;

Thus, foldr g b [a_0, ..., a_n] computes

g($$a_0$$, g($$a_1$$, g($$a_2$$, ... g($$a_{n}$$, b) ... )))

and foldl g b [a_0, ..., a_n] computes

g($$a_{n}$$, g($$a_{n-1}$$, g($$a_{n-2}$$, ..., g($$a_{0}$$, b) ... )))

The “fold-right” function reduces the elements in a list to a single value by repeated application of $$g$$, starting at the right of the list and working to the left. The "fold-left" function starts from the left and works to the right.

Here is an example usage, which defines a function sum that adds together the numbers in a list:

- fun add(x,y) = x+y;
- fun sum elems = foldr add 0 elems;
- sum [2,3,4];
val it = 9: int

In effect, sum [2,3,4] computes

add(2, add(3, add(4, 0)))

Writing that function recursively would give us:

fun sum_rec nil = 0
| sum_rec (x::xs) = x + sum_rec(xs);

which computes the exact same value: sum_rec [2,3,4] computes $$2 + (3 + (4 + 0))$$. Many computations involve traversing a list and computing a “summary” value for it. We explore other examples below, and our folding operations enable us to write them in a succinct, elegant way.

We could also define sum using foldl:

- fun sum2 elems = foldl add 0 elems;

in which case sum2 [2,3,4] computes

add(4, add(3, add(2, 0)))

Of course, we typically combine folding with anonymous functions, as in the following definition of sum:

- fun sum elems = foldr (fn (x,result) => (x+result)) 0 elems;

The type of both foldr and foldl is

('c * 'd -> 'd) -> 'd -> 'c list -> 'd

That is, it takes as parameters a reducing function, an initial value, and a list. It produces a single summary value.

1. Using a fold operation, write a function concatWords: string list -> string. This function should return return a string with all strings in the list concatenated:

- concatWords nil;
val it = "" : string
- concatWords ["Three", "Short", "Words"];
val it = "ThreeShortWords" : string
2. Using a fold operation, write a function words_length: string list -> int. This function should return the total length of all words appearing in a list of strings. For example:

- words_length nil;
val it = 0 : int
- words_length ["Three", "Short", "Words"];
val it = 15 : int
1. Can we always use foldl in place of foldr? If yes, explain. If no, give an example function f, list l, and initial value v such that foldr f v l and foldl f v l behave differently.

2. Using a fold, write a function count: ''a -> ''a list -> int. It computes the number of times a value appears in a list. For example:

- count "sheep" ["cow", "sheep", "sheep", "goat"];
val it = 2 : int
- count 4 [1,2,3,4,1,2,3,4,1,2,3,4];
val it = 3 : int
3. Using a fold, write a function partition: int -> int list -> int list * int list that takes an integer $$p$$ and a list of integers $$l$$, and that returns a pair of lists containing the elements of $$l$$ smaller than $$p$$ and those greater than or equal to $$p$$. The ordering of the original list should be preserved in the returned lists. (We wrote a recursive form during lecture as part of quicksort.)

- partition 10 [1,4,55,2,44,55,22,1,3,3];
val it = ([1,4,2,1,3,3],[55,44,55,22]) : int list * int list
4. Using a fold, write a function poly: real list -> (real -> real) that takes a list of reals [a_0, a_1, ..., a_{n-1}] and returns a function that takes an argument b and evaluates the polynomial $a_0 + a_1 x + a_2 x^2 + \cdots + a_{n-1} x^{n-1}$ at $$x = b$$; that is, it computes $$\sum_{i=0}^{n-1} a_i b^i$$. For example,

- val g = poly [1.0, 2.0];
val it = fn: real -> real
- g(3.0);
val it = 7.0: real
- val g = poly [1.0, 2.0, 3.0];
val it = fn: real -> real
- g(2.0);
val it = 17.0: real

(Hint: $$a_0 + a_1 x + a_2 x^2 + a_3 x^3 = a_0 + x (a_1 + x (a_2 + x a_3))$$. This is an example of Horner’s Rule. Horner’s Rule demonstrates that we can evaluate a degree $$n$$ polynomial with only $$O(n)$$ multiplies.)