(* lecture 7: more higher-order functions; composition of functions *) (* Applies function F to each element of the given list [a,b,c,...], producing a new list [F(a),F(b),F(c),...]. *) fun map(F, []) = [] | map(F, first::rest) = F(first) :: map(F, rest); (* Calls function P on each element of the given list [a,b,c,...]; P is an inclusion test that returns either true or false. The elements for which P returns true are kept; the others discarded. *) fun filter(P, []) = [] | filter(P, first::rest) = if P(first) then first :: filter(P, rest) else filter(P, rest); exception EmptyList; (* Calls function F successively on pairs of elements from the given list to combine pairs into a single element until only one element remains. *) fun reduce(F, []) = raise EmptyList | reduce(F, [value]) = value | reduce(F, first::rest) = F(first, reduce(F, rest)); (* A helper operator to produce a range of numbers; a--b produces [a, a+1, ..., b-1, b]. *) infix --; fun min--max = if min > max then [] else min :: (min + 1 -- max); (* Computes n choose k; the number of unique combinations of k things that can be chosen from n elements. This is relevant for Pascal's triangle because element (r, c) of the triangle is equal to combin(r, c). *) fun combin(n, k) = if k = 1 then n else if k = 0 orelse k = n then 1 else combin(n-1,k) + combin(n-1,k-1); (* Produces row #r of Pascal's trangle. Assumes r >= 0. *) fun row(r) = let fun helper(k) = combin(r, k) in map(helper, 0 -- r) end; (* Produces the first n rows of Pascal's triangle. Assumes n >= 0. *) fun triangle(n) = map(row, 0--(n-1)); (* uber-1337 version all on one line with anonymous functions *) fun triangle2(n) = map(fn(r) => map(fn(k) => combin(r, k), 0 -- r), 0--(n-1)); (* test data *) val test = [4, ~5, 6, ~19, ~42, 31, ~2];