Edit this page Backlinks This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ====== Lab 3. Higher-order functions ====== Objectives: * implement and use **higher-order** functions. A **higher-order** function takes other functions as parameter or returns them * implement **curry** and **uncurry** functions, and how they should be properly used (review lecture). **3.1.** Define the function ''foldWith'' which uses an operation ''op'', and an initial value ''b'' to reduce a range of integers to a value. For instance, given that ''op'' is addition (+), the result of folding the range 1 to 3 with ''b = 0'' will be ''( ( 0 + 1 ) + 2 + 3 = 6''. ''foldWith'' should be **curried** (it will take the operation and return another function which expects the bounds). <code scala> def foldWith (b: Int)(op: (Int,Int) => Int)(start: Int, stop: Int): Int = { def tail_fold(crt: Int, acc: Int): Int = ??? ?? } </code> **3.2.** Define the function ''foldConditional'' which extends ''foldWith'' by also adding a predicate ''p: Int => Int''. ''foldConditional'' will reduce only those elements of a range which satisfy the predicate. <code scala> def foldConditional(b: Int)(op: (Int,Int) => Int, p: Int => Boolean)(start: Int, stop: Int): Int = ??? </code> **3.3.** Implement the function ''foldRight'' which has the same behaviour as ''foldWith'', but the order in which the operation is performed is now: ''1+(2+(3+0))=6''. What is the simplest way to implement it? **3.4.** Write a function ''foldMap'' which takes values $math[a_1, a_2, \ldots, a_k] from a range and computes $math[f(a_1)\;op\;f(a_2)\;op\;\ldots \;op\;f(a_k)]. <code scala> def foldMap(op: (Int,Int) => Int, f: Int => Int)(start: Int, stop: Int): Int = ??? </code> **3.5.** Write a function which computes $math[1 + 2^2 + 3^2 + \ldots + (n-1)^2 + n^2] using ''foldMap''. <code scala> def sumSquares(n: Int): Int = ??? </code> **3.6.** Write a function ''hasDivisor'' which checks if a range contains a multiple of k. Use ''foldMap'' and choose ''f'' carefully. <code scala> def hasDivisor(k: Int, start: Int, stop: Int): Boolean = ??? </code> **3.7.** We can compute the sum of an area defined by a function within a range a,b (the integral of that function given the range), using the following recursive scheme: * if the range is small enough, we treat f as a line (and the area as a trapeze). It's area is $math[(f(a) + f(b))(b-a)/2]. * otherwise, we compute the mid of the range, we recursively compute the integral from a to mid and from mid to b, and add-up the result. Implement the function ''integrate'' which computes the integral of a function f given a range: <code scala> def integrate(f: Double => Double)(start: Double, stop: Double): Double = ??? </code> **3.8.** We define ''Line2D'' to be lines in a 2-dimensional space, and we represent them as functions. Write a function which takes a Line2D and translates it up on the Ox axis by a given offset. For instance, translateOx of 2 on y=x+1 will return y=x+3. <code scala> type Line2D = Int => Int def translateOx(offset: Int)(l: Line2D): Line2D = ??? </code> **3.9.** (!) Write a function which takes a Line2D and translates it up on the Oy axis by a given offset. <code scala> def translateOy(offset: Int)(l: Line2D): Line2D = ??? </code> **3.10.** Write a function which takes two lines, and checks if there exist integer coordinates within a given range for x, where the lines intersect. <code scala> def intersect(l1: Line2D, l2: Line2D)(start: Int, stop: Int): Boolean = ??? </code> **3.11.** Write a function which takes two lines and a range of integers, and checks if l1 has larger y values than l2 over the entire range. <code scala> def larger(l1: Line2D, l2: Line2D)(start: Int, stop: Int): Boolean = ??? </code>