Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
fp:lab04 [2021/04/08 15:35] pdmatei |
fp:lab04 [2022/05/15 23:54] (current) vbadoiu old revision restored (2022/03/25 10:15) |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== 4. Higher order functions ====== | + | ===== 4. Lists in Scala ===== |
- | ===== 4.1. Map, foldl, foldr, filter, zipWith ===== | + | Objectives: |
+ | * get familiar with **pattern matching** lists, as well as common list operations from Scala and how they work | ||
+ | * get familiar with common **higher-order functions** over lists (partition, map, foldRight, foldLeft, filter) | ||
- | ==== Map ==== | + | ==== 4.1. Common list operations ==== |
- | The function ''map'' has signature: ''(a->b) -> [a] -> [b]''. It takes as parameter: | + | |
- | - a **transformer** function ''f :: a->b'' | + | |
- | - a list of objects of type ''a'' | + | |
- | It returns: | + | **4.1.1.** Write a function which returns true if a list of integers has at least k elements. Use patterns. |
- | - a list of transformed objects of type ''b'' | + | <code scala> |
+ | def atLeastk(k: Int, l: List[Int]): Boolean = | ||
+ | if (k == 0) ??? | ||
+ | else ??? | ||
+ | } | ||
+ | </code> | ||
- | 4.1.1. Write a function which takes a list of integers and adds 4 to **each element**. | + | **4.1.2.** Write a function which returns the first ''n'' elements from a given list. The function should not be implemented as tail-recursive. |
+ | <code scala> | ||
+ | def take(n: Int, l: List[Int]): List[Int] = ??? | ||
+ | //take(3,List(1,2,3,4,5)) = List(1,2,3) | ||
+ | </code> | ||
- | 4.1.2. Write a function which takes a list of strings and adds a whitespace at the **beginning** of each string. | + | **4.1.3.** Write a function which //drops// the first ''n'' elements from a given list. The function should not be implemented as tail-recursive. |
+ | <code scala> | ||
+ | def drop(n: Int, l: List[Int]): List[Int] = ??? | ||
+ | //drop(3,List(1,2,3,4,5)) = List(4,5) | ||
+ | </code> | ||
- | 4.1.3. Write a function which takes a value k, a list of **strings** and returns a list with the first k characters of each string. | + | **4.1.4.** Write a function which takes a predicate ''p: Int => Boolean'', a list ''l'' and returns a sublist of ''l'' containing those elements for which ''p'' is true. The function should be **curried**. |
+ | <code scala> | ||
+ | def takeP(p: Int => Boolean)(l: List[Int]): List[Int] = ??? | ||
+ | //takeP(_%2 == 0)(List(1,2,3,4,5,6)) = List(2,4,6) | ||
+ | </code> | ||
- | ==== Filter ==== | + | **4.1.5.** Write a function which uses a predicate to partition (split) a list. |
+ | <code scala> | ||
+ | def part(p: Int => Boolean)(l: List[Int]): (List[Int], List[Int]) = ??? | ||
+ | // part(_%2 == 0)(List(1,2,3,4,5,6)) = (List(2,4,6),List(1,3,5)) | ||
+ | </code> | ||
- | The function ''filter :: (a -> Bool) -> [a] -> [a]'' takes as parameter: | + | ==== 4.2. Gradebooks ==== |
- | * a **predicate** (or condition) of type ''(a -> Bool)'' | + | More general implementation of ''taken'', ''dropn'' and ''part'' are already implemented in Scala and can be used as member functions of lists. Examples are shown below: |
- | * a list of elements of type ''a'' | + | <code scala> |
+ | val l = List(1,2,3,4,5,6,7,8,9) | ||
+ | l.take(3) | ||
+ | l.drop(3) | ||
+ | l.partition(_%2 == 0) | ||
+ | </code> | ||
- | It returns: | + | In what follows, we shall encode a gradebook as a list of pairs ''(<name>,<grade>)'', where ''<name>'' is a String and ''<grade>'' is an Int. Example: |
- | * a list of filtered elements using the predicate. | + | <code scala> |
+ | val gradebook = List(("G",3), ("F", 10), ("M",6), ("P",4)) | ||
+ | </code> | ||
- | 4.1.4. Write a function which removes all strings which are equal to the empty string. | + | To make the type signatures more legible, we can introduce type aliases in Scala: |
+ | <code scala> | ||
+ | type Gradebook = List[(String,Int)] //the type Gradebook now refers to a list of pairs of String and Int | ||
+ | </code> | ||
+ | Add this type alias to your code before solving the following exercises. | ||
- | 4.1.5. Write a function which takes a list of strings and returns only those which start with a capital. | + | **4.2.1.** Write a function which adds one point to all students which have a passing grade (>= 5), and leaves all other grades unchanged. |
+ | <code scala> | ||
+ | def increment(g: Gradebook): Gradebook = | ||
+ | g.map(???) | ||
+ | </code> | ||
- | ==== Foldr ==== | + | **4.2.2.** Find the average grade from a gradebook. You must use ''foldRight''. |
+ | <code scala> | ||
+ | def average(g: Gradebook): Double = ??? | ||
+ | </code> | ||
- | The function ''foldr'' has type ''(a -> b -> b) -> b -> [a] -> b''. It takes as parameter: | + | **4.2.3.** Write a function which takes a gradebook and returns the percentage of failed vs. passed students, as a pair (x,y). |
- | * a **binary** operation ''a -> b -> b''. It takes a "list" element of type ''a'', and an **accumulator** of type ''b'' and returns an element of type ''b'' | + | <code scala> |
- | * an **accumulator** (or initial value) of type ''b'' | + | def percentage(g: Gradebook): (Double,Double) = ??? |
- | * a list with elements of type ''a'' | + | </code> |
- | It returns: | + | **4.2.4.** Write a function which takes a gradebook and returns the list of names which have passed. Use filter and map from Scala. |
- | * a **folded** (or reduced) value of type ''b''. | + | <code scala> |
+ | def pass(g: Gradebook): List[String] = ??? | ||
+ | </code> | ||
- | Example: | + | **4.2.5.** Implement merge-sort (in ascending order) over gradebooks: |
- | <code haskell> | + | <code scala> |
- | foldr (*) 0 [1,2,3] = 1 * (2 * (3 * 0)) | + | def mergeSort(l: Gradebook): Gradebook = { |
+ | def merge(u: Gradebook, v: Gradebook): Gradebook = ??? | ||
+ | ??? | ||
+ | } | ||
</code> | </code> | ||
- | 4.1.6. Write a function using foldr which computes the product of a list of integers. | + | **4.2.6** Write a function which takes a gradebook and reports all passing students in **descending** order of their grade. |
- | + | <code scala> | |
- | 4.1.7. Write a function which computes the maximum of a list of **positive** integers using foldr. | + | def honorsList(g: Gradebook): List[String] = ??? |
- | + | ||
- | 4.1.8. Write a function which concatenates a list of strings using foldr. | + | |
- | + | ||
- | ==== Foldl ==== | + | |
- | + | ||
- | The function ''foldl'' has type ''(b -> a -> b) -> b -> [a] -> b''. It takes as parameter: | + | |
- | * a **binary** operation ''b -> a -> b''. It takes an **accumulator** of type ''b'', a "list" element of type ''a'' and returns an element of type ''b'' | + | |
- | * an **accumulator** (or initial value) of type ''b'' | + | |
- | * a list with elements of type ''a'' | + | |
- | + | ||
- | It returns: | + | |
- | * a **folded** (or reduced) value of type ''b''. | + | |
- | + | ||
- | Unlike foldr, foldl reduces element in a different order: | + | |
- | Example: | + | |
- | <code haskell> | + | |
- | foldl (*) 0 [1,2,3] = ((0 * 1) * 2) * 3 | + | |
</code> | </code> | ||
- | |||
- | 4.1.9. Write a function which uses foldl to check if an element is member of a list. | ||
- | |||
- | 4.1.10. Write a function which uses foldl to implement the reversal of a list. | ||
- | |||
- | |||
- | ==== zipWith ==== | ||
- | |||
- | 4.1.11. Use ''ghci> :t zipWith'' to inspect the type of ''zipWith''. Think about a possible example to run this function. What does it do? | ||
- | |||
- | |||
- |