Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
fp:lab03 [2021/03/25 14:32]
pdmatei
fp:lab03 [2022/03/18 15:31] (current)
pdmatei
Line 1: Line 1:
-====== 3. Recursive functions and tail-end recursion ​======+====== 3. Higher-order functions ​======
  
-===== 3.1Pattern matching revisited =====+Objectives:​ 
 +  * implement and use **higher-order** functionsA **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).
  
-It is likely that in the above implementations you used ''​head'' ​and ''​tail'', or branch definitions combined with '_' to solve the exercises. Haskell supports ​more elegant means of //value introspection//,​ called **pattern matching**. For instance, ​in:+**3.1.** Define ​the function ​''​foldWith'' ​which uses an operation ​''​op''​ to reduce ​range of integers to a value. For instance, ​given that ''​op''​ is addition (+), the result of folding the range 1 to 3 will be 1+2+3=6. ''​foldWith''​ should be curried (it will take the operation and return another function which expects the bounds).
  
-<​code ​haskell+<​code ​scala
-f [] ... +def foldWith (op: (Int,​Int) ​=> Int)(start: Int, stop: Int): Int = { 
-(h:t) = ... +  def tail_fold(crtInt, acc: Int): Int  ​??? 
-</​code> ​+  ?? 
 +} 
 +</​code>​
  
-''​(h:t)'' ​is a **pattern** ​which denotes a non-empty list where ''​h'' ​is the first element and ''​t'' ​is the rest of the listIn fact, ''​[]'' ​is also pattern denoting ​the empty listsPatterns are **allways** surrounded by round parentheses. They can also be composite, as in the exercise below:+**3.2.** Define the function ​''​foldConditional''​ which extends ​''​foldWith'' ​by also adding a predicate ​''​p: Int => Int''​. ''​foldConditional'' ​will reduce only those elements of range which satisfy ​the predicate.
  
-3.1.1. Write a function which returns the number of elements from a list. Use patterns.+<code scala> 
 +def foldConditional(op:​ (Int,Int) => Int, p: Int => Boolean)(start:​ Int, stop: Int): Int = ??? 
 +</​code>​
  
-3.1.2. Write a function which takes a list of integer lists, and concatenates them. (E.g''​f [ [1,2,3],[4,5] [1,2,3,4,5]''​).+**3.3[//should be revised//] ** Let $math[count_k(n) = k + 2k + 3k + ... x*k], with $mathx*k \leq nbe the sum of all multiples of $math[k] within the range 1,n. Write a function ''​alldivs''​ which computes the sum: $math[count_1(n) + count_2(n) + ... + count_k(n)]. (Hint, use ''​foldConditional''​). ​
  
-3.1.3 (!) Write the **same** function, this time using only the **cons** ('':''​) operator as well as **patterns**. Hint: +<​code ​scala
-<​code ​haskell+def alldivs(nInt)Int ???
-[[1,​2,​3],​[4,​5]] = +
-1:[[2,​3],​[4,​5]] = +
-1:2:​[[3],​[4,​5]] ​= +
-1:​2:​3:​[[],​[4,​5]] = +
-1:​2:​3:​[[4,​5]] = +
-1:​2:​3:​4:​[[5]] =  +
-1:​2:​3:​4:​5:​[[]] = +
-1:​2:​3:​4:​5:​[]+
 </​code>​ </​code>​
  
-3.1.4. Write a function which removes duplicates ​from a list of integers.+**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 f(a_k)]. 
 +<code scala> 
 +def foldMap(op: (Int,Int) => Int, f: Int => Int)(start: Int, stop: Int): Int = ??? 
 +</​code>​
  
-===== 3.2. Tail-end recursive functions =====+**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.2.1 Solve exercise 3.1.3. using tail-recursive ​function.+**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.2.2. Solve exercise 3.1.4. using tail-recursive function.+**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 to mid and from mid to b, and add-up the result.
  
-3.2.3. Return all duplicates from a list, using a tail-recursive ​function. E.g., the duplicates from list ''​[1,​2,​3,​4,​2,​4,​2,​1]'' ​are ''​[2,​4,​2,​1]''​. +Implement the function ''​integrate''​ which computes ​the integral ​of a function ​f given range
- +<​code ​scala
-===== 3.3. Strings in Haskell ===== +def integrate(f:​ Double ​=> Double)(start:​ Double, stop: Double): Double ​???
- +
-In Haskell, strings are implemented as **lists of type** ''​Char''​. For instance '''​a'​ ''​ is a ''​Char''​. Also, the string ''"​abc"''​ is the same as: ''​ '​a':'​b':'​c':​[]''​. Strings can be introspected (using pattern matching) and constructed exactly as any other list (using cons '':'',​ ''​++'',​ etc.). +
- +
-3.3.1. Write a function ​which takes a list of words and makes the first letter ​of each word uppercase. (Hint: google ​respective ​function ​of chars). +
- +
-3.3.2. Write function which takes a list of words and makes **all** letters uppercase. +
- +
-3.3.3. (!) Write a function which takes a text and a pattern and returns the number of occurrences of the pattern in the text. Do **not** use auxiliary functions. +
-Example+
-<​code ​haskell>  +
-search "I eat green apples"​ "​eat" ​+
-search "​ababaab"​ "​aba" ​2+
 </​code>​ </​code>​
- 
- 
- 
- 
-