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:lab06 [2021/04/15 15:56]
pdmatei
fp:lab06 [2022/04/08 12:45] (current)
pdmatei
Line 1: Line 1:
-====== ​6Functional closures ​======+====== ​Lab 06Polymorphism in Scala ======
  
-==== Function application and composition as higher-order functions ==== +This lab will start with the implementations discussed during lecture. Please find the polymorphic trait ''​FList[A]''​ below: 
-One key idea from functional programming is that functions are **first-class** ​(or **first-order**values, just like integersstrings, etc. . They can be passed as function **arguments** and also be returned by function application.+<code scala> 
 +trait FList[A]{ // list with elements of type A 
 +  def length: Int 
 +  def head: A 
 +  def tail: FList[A] 
 +  def map[B](f: A => B): FList[B] 
 +  // a op (b op (c op acc)) 
 +  def foldRight[B](acc:​ B)(op: (A,B) => B): B 
 +  // ​((acc op aop b) op c 
 +  def foldLeft[B](acc:​ B)(op: (B,A) => B): B 
 +   
 +  def contains(e: A):Boolean = 
 +    this.foldRight(false)(_ == e || _) 
 +   
 +
 +</​code>​
  
-Functions which //take other functions as parameter// are called **higher-order**. ​+together with the implementations:​ 
 +<code scala> 
 +case class FNil[A]() extends FList[A]{ 
 +  override def length: Int = 0 
 +  override def head: A = throw new Exception("​head on empty list"​) 
 +  override def tail: FList[A] = throw new Exception("​head on empty list"​) 
 +  override def map[B](f: A => B): FList[B] = FNil[B] 
 +  override def foldRight[B](acc:​ B)(op: (A,B) => B): B = acc 
 +  override def foldLeft[B](acc:​ B)(op: (B,A) => B): B = acc 
 +}
  
-==== Lambdas ==== +case class Cons[A](x:​A,​ xs:​FList[A]) extends FList[A]{ 
-46. Functions can be passed as arguments just like any other value value. Alsofunctions can be returned as parameterIn order to do soit is convenient to define functions without naming themThis is done using **lambda**'​s. For a more detailed discussion regarding lambdassee the lecture. The following definitions are equivalent:+  override def length ​1 + xs.length 
 +  override def head:​A ​
 +  override def tail:​FList[A] ​xs 
 +  override def map[B](f: A => B): FList[B] ​= 
 +    Cons(f(x),​xs.map(f)) 
 +  override def foldRight[B](acc:​ B)(op: (A,B) => B): B 
 +    op(xxs.foldRight(acc)(op)) 
 +  override def foldLeft[B](acc:​ B)(op: (B,A) => B): B = 
 +    xs.foldLeft(op(acc,x))(op) 
 +  }
  
-<code haskell> 
-f x y = x + y  
-f x = \y -> x + y 
-f = \x -> \y -> x + y 
-f = \x y -> x + y 
 </​code>​ </​code>​
  
-==== 6.1Warm-up ====+Add the following methods in the trait ''​FList''​ and implement them**Some methods can be directly implemented in the trait, using ''​map'',​ ''​foldRight'',​ ''​foldLeft''​ or other functions.**  
 +  * Can you figure which ones are best implemented in the trait and which in the case classes?
  
-Consider an URL such as: ''​domain-name.com/​books/​get_item?​param1=1234&​param2=5678''​In the previous example: +**6.1.** ''​indexOf'' ​determines the position of value in the list (starting with 0) 
-  ​* ''​books'' ​is resource-name +<code scala> 
-  * ''​get_item''​ is an action +def indexOf(e: A): Int 
-  * ''​param1''​ and ''​param2''​ are parameters with associated values ''​1234''​ and ''​5678''​ respectively.+</​code>​
  
-6.1.1. Write the following functions:​ +**6.2.** ''​update'' ​creates a new list where the given position is modified with a new value: 
-  ​''​get_resource''​ +<code scala> 
-  ​* ''​get_action''​ +//​Cons(1,​Cons(2,​Cons(3,​FNil()))).update(9,​1) = Cons(1,​Cons(9,​Cons(3,​FNil()))) 
-  * ''​get_params''​+def update(e: A, pos: Int): FList[A] 
 +</​code>​
  
-which extract the resource name, the action and the parameters of a given URL (represented as string)Write yourself the signature of the functionsWhen implementing,​ try to: +**6.3.** ''​append''​ concatenates this list to another
-  * generalise as much as possible +<code scala> 
-  * use higher-order functions and composition+def append(l: FList[A]): FList[A] 
 +</​code>​
  
-6.1.2. Given a list of URLs, extract those which satisfy, at the same time the following constraints:​ +**6.4.** ''​reverse'' ​returns the reversed list: 
-  ​have the domain name equal to "​gmail.com"​ or "​yahoo.com"​ +<code scala> 
-  ​have the resource equal to "​books"​ or "​movies"​ +def reverse: FList[A] 
-  * have an action from the set ''​{get_item, remove_item,​ insert_item}''​ +</​code>​
-  * have at least three parameters+
  
-Choose the most effective way of writing your code such that: +**6.5.** ''​last'' ​returns ​the last element of the list
-  ​your code is easy to use +<​code ​scala
-  ​your code is easy to **extend** +def last: A 
- +</​code>​
-===== 6.2A predicate-based implementation for sets ===== +
-6.2.1. Consider ​**sets** represented as characteristic functions with signature ​''​s :: Integer -> Bool''​, where ''​s x''​ is true if ''​x''​ a member in the set. Examples+
-<​code ​haskell+
-s1 1 = True +
-s1 2 = True +
-s1 _ = False +
- +
-s2 x = mod x 2 == 0 +
- +
-s3 _ = False+
  
 +**6.6.** ''​filter''​ filters the elements of the list:
 +<code scala>
 +def filter(p: A => Boolean): FList[A]
 </​code>​ </​code>​
-Above, ''​s1''​ is the set $math[\{1,​2\}],​ ''​s2''​ is the set of even integers and ''​s3''​ is the empty-set. Write a function which tests if an element is a member of a set: 
-<code haskell> 
-mem :: (Integer -> Bool) -> Integer -> Bool 
-mem = ... 
-</​code>​ 
- 
-6.2.2. Define the set $math[\{2^n \mid n\in\mathbb{N}\}]. ​ 
- 
-6.2.3. Define the set of natural numbers. 
  
-6.2.4Implement ​the intersection of two sets. Use lambdas+**6.7.** ''​zip''​ combines two lists into a list of pairsIf **either** list is larger, ​the remaining elements are discarded
-<​code ​haskell+<​code ​scala
-intersection :: (Integer -> Bool-> (Integer -> Bool-> (Integer -> Bool)+// Cons(1,​(Cons(2,​Cons(3,​FNil()))).zip(Cons(true,​Cons(false,​Cons(true,​FNil())))) = 
 +// Cons((1,​true),​Cons((2,​false),​Cons((3,​true),​FNil()))) 
 +def zip[B](l: FList[B]): FList[(A,B)]
 </​code>​ </​code>​
  
-6.2.5. Write intersection in another way, (without using lambdas).  +**6.8.** ''​insSorted''​ inserts an element into a sorted list so that the result is a sorted list
-<​code ​haskell+<​code ​scala
-intersection' ​:: (Integer -Bool-> (Integer -> Bool-> Integer -> Bool+def insSorted(fA =Int)(e: A): FList[A]
 </​code>​ </​code>​
  
-6.2.6. Write a function which takes a list of integers, and returns the set which contains them+**6.9.** ''​sortBy''​ sorts a list using insertion sort
-<​code ​haskell+<​code ​scala
-toSet :: [Integer-> (Integer -> Bool)+def sortBy(fA => Int)FList[A]
 </​code>​ </​code>​
  
-6.2.7. Implement a function ​which takes a list of sets and computes their intersection. +**6.10 (!)** Implement a method ''​pack'' ​which encodes ​sorted ​list as follows: 
- +<​code ​scala
-<​code ​haskell+[1,​1,​1,​2,​3,​4,​4,​5,​6].pack = [(1,​3),​(2,​1),​(3,​1),​(4,​2),​(5,​1),​(6,​1)] 
-capList :: [Integer -> Bool-> Integer -> Bool+def packFList[(A,Int)]
 </​code>​ </​code>​
-