For the material covered Dec 5 (drawn from Sections 7.5 and 7.14),
I'm giving some problems that don't appear in the book.
Enter these in the automated grading system as "7.14.a"
etc, even though some of these are more related to Section 7.5.
For reference, here is the code for map,
filter, and foldr.
You'll need these in the interpreter to run your code.
fun map(f, []) = [] | map(f, a::rest) = f(a)::map(f, rest); fun filter(f, []) = [] | filter(f, a::rest) = if f(a) then a::filter(f, rest) else filter(f, rest); fun foldr(f, s, []) = s | foldr(f, s, x::rest) = f(x, foldr(f, s, rest));
Remember that to use foldr to make
function someFunction, do something like this:
fun someFunction(xx) = foldr(fn(x, y) => ??, ??, xx)
...where the first ?? indicates how to combine
the next item in the list x with the running result
y, and the second ?? indicates
what the seed value is.
7.14.a
Use foldr
to write a function catAll that takes
a list of lists and concatenates them all into a single list.
Here is the non-foldr version:
fun catAll([]) = [] | catAll(xx::rest) = xx @ catAll(rest);
For example:
- catAll([[1,2], [], [3,4,5], [6]]); val it = [1,2,3,4,5,6] : int list
7.14.b
Use foldr to write a function
numEvens that takes a list of ints
and counts the number of evens.
Here is a non-foldr version:
fun numEvens([]) = 0 | numEvens(a::rest) = (if a mod 2 = 0 then 1 else 0) + numEvens(rest);
For example:
- numEvens([1,2,3,4,5,6,7]); val it = 3 : int
7.14.c
Recall this new version of the "brute force"
versions of evaluatePoly
that we did in class:
fun evaluatePoly([], x) = 0.0
| evaluatePoly(c::rest, x) = c * pow(x, count(rest)) + evaluatePoly(rest, x);
fun evaluatePoly(coeffs, x) =
(* evalPolyHelper returns a tuple containing the
the value of resulting the sub-polynomial and the
current power of x *)
let
fun evalPolyHelper([]) = (0.0, 1.0)
| evalPolyHelper(c::rest) =
let val (v, p) = evalPolyHelper(rest)
in
(c*p + v, x * p)
end;
in
#1(evalPolyHelper(coeffs))
end;
Use foldr to write a new version;
here is a stub:
fun evaluatePoly(coeffs, x) =
#1(foldr(fn(c, (y, px)) => ( ??, ??), (??, ??), coeffs));
The #1 is because the combining function
returns a tuple containing the running result and the current power
of x. At the end we care only about the
running (now final) result.
(This problem appears in the book as Problem 7.B in Section 7.14,
which you can see for a fuller explanation if necessary.)
Don't confuse evaluatePoly with the
unrelated function evaluatePohly.
7.14.d
We have seen two versions of scale,
a function that takes a list and a factor and scales each element in
the list by the given factor.
Here is the original version:
fun scale(f, []) = [] | scale(f, x::rest) = x * f :: scale(f, rest);
Here is a version that uses map:
fun scale(f, xx) = map (fn (x) => f * x, xx);
However, this also can be written using foldr.
Finish the following stub:
fun scale(f, xx) = foldr(fn(x, y) => ??, ??, xx);
Hint: In the anonymous function passed to foldr
the parameter y is a list.
(A similar problem appears as 7.5.5 in the book.)
7.14.e
When you compare the foldr version of
scale to the map version of
scale, it suggests that foldr is
a more primitive/basic/general operation than map.
In fact, you can rewrite map using foldr.
Finish the following stub:
fun map(f, xx) = foldr(fn(x,y) => ??, ??, xx);
(A similar problem appears as 7.5.7 in the book.)