# Conference: Week 5

#### Table Of Contents

### 1. Admistrativia

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.
- Will download and submit via Gradescope.

- Up to

### 2. Type Inference

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

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

### 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;
- 2,3,4];
- sum [val it = 9: int
```

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

computes

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

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

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

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

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

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

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 "Three", "Short", "Words"]; - concatWords [val it = "ThreeShortWords" : string`

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 "Three", "Short", "Words"]; - words_length [val it = 15 : int`

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.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:`"sheep" ["cow", "sheep", "sheep", "goat"]; - count val it = 2 : int 4 [1,2,3,4,1,2,3,4,1,2,3,4]; - count val it = 3 : int`

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.)`10 [1,4,55,2,44,55,22,1,3,3]; - partition val it = ([1,4,2,1,3,3],[55,44,55,22]) : int list * int list`

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 3.0); - g(val it = 7.0: real val g = poly [1.0, 2.0, 3.0]; - val it = fn: real -> real 2.0); - g(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.)