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:19]
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) => IntpInt => Boolean)(startIntstopInt)Int ???
-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.1.3 (!) Write the **same** function, this time using only the **cons** ('':''​) operator as well as **patterns**. Hint: +
-<​code ​haskell+
-[[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.3[//should be revised//] ** Let $math[count_k(n) = k + 2k + 3k + ... x*k], with $math[ x*k \leq n] be 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.2. Tail-end recursive functions ===== +<code scala> 
- +def alldivs(n: Int): Int ???
-3.2.1 Solve exercise 3.1.3. using a tail-recursive function. +
- +
-3.2.2. Solve exercise 3.1.4. using a tail-recursive function. +
- +
-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]''​. +
- +
-===== 2.3. Strings in Haskell ===== +
- +
-2.3.1. Write a function which takes a list of words and makes the first letter of each word uppercase. +
- +
-2.3.2. Write a function which takes a list of words and makes **all** letters uppercase. +
- +
-2.3.3. ​(!Write a function which takes a text and a pattern and returns the number of occurrences of the pattern in the text.  +
-Example: +
-<code haskell>  +
-search "I eat green apples"​ "​eat"​ = 1 +
-search "​ababaab"​ "​aba" ​2+
 </​code>​ </​code>​
  
-2.3.4. (!) What does ''​f'', ​defined in exercise 2.2.4.do (note that ''​Matei''​ and ''​Mihai''​ both start with letter '​M'​)? Write an implementation for ''​f''​. +**3.4.** Write a function ​''​foldMap'' ​which takes values $math[a_1a_2\ldots, a_k] from a range and computes $math[f(a_1)\;op\;f(a_2)\;​op\;​\ldots f(a_k)]
- +<​code ​scala
-2.3.5. Write the signature and implement the following function: +def foldMap(op: (Int,Int) => Intf: Int => Int)(start: Intstop: Int): Int = ???
-<​code ​haskell+
-   f ["​Matei"​"​Mihai"​] ["​Popovici"​,"​Dumitru"​] ​[("​Matei","​Popovici"​)("​Mihai"​,"​Dumitru"​)]+
 </​code>​ </​code>​
  
-2.3.6Implement the following ​function: +**3.5.** Write a function ​which computes $math[1 + 2^2 + 3^2 + \ldots + (n-1)^2 + n^2] using ''​foldMap''​. 
-<​code ​haskell+<​code ​scala
-   f ["​Matei",​ "​Mihai"​] ["​Popovici","​Dumitru"​] ​["​MPopovici",​ "​MDumitru"​]+def sumSquares(n:​ Int): Int ???
 </​code>​ </​code>​
  
-2.3.7. Write a function which takes list of pairs - student-name ​and grade, removes those with grades less than 5, splits the name in substrings, and adds one bonus point to people with three namesExample: +**3.6.** Write a function ​''​hasDivisor'' ​which checks if range contains a multiple ​of k. Use ''​foldMap'' ​and choose ''​f''​ carefully
-<​code ​haskell+<​code ​scala
-    f [("Dan Matei Popovici"​,9),("​Mihai",​4),​("​Andrei Alex",​6)] ​= +def hasDivisor(k: Intstart: Intstop: Int): Boolean ​???
-    [(["​Dan",​ "​Matei",​ "​Popovici"​],​10),​(["​Andrei",​ "​Alex"​],​6)]+
 </​code>​ </​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>​