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
pp:l03 [2020/03/24 14:22]
pdmatei
pp:l03 [2022/03/20 15:13] (current)
bogdan.deac
Line 1: Line 1:
-====== Higher-order functions ======+====== ​3. Higher-order functions ======
  
 ==== Function application and composition as higher-order functions ==== ==== Function application and composition as higher-order functions ====
 One key idea from functional programming is that functions are **first-class** (or **first-order**) values, just like integers, strings, etc. . They can be passed as function **arguments** and also be returned by function application. One key idea from functional programming is that functions are **first-class** (or **first-order**) values, just like integers, strings, etc. . They can be passed as function **arguments** and also be returned by function application.
  
-Functions which //take other functions as parameter// are called **higher-order**. We have already encountered two such functions, i.e. ''​($)''​ and ''​(.)''​.  +Functions which //take other functions as parameter// are called **higher-order**. ​
- +
-43. Define the operator ''​($)''​ from [[pp:​l02|Lab 2]] as a higher-order function. +
- +
-44. What type should functional composition have?  +
- +
-45. Define function composition.+
  
 ==== Lambdas ==== ==== Lambdas ====
-46. Functions can be passed as arguments just like any other value value. Also, functions can be returned as parameter. In order to do so, it is convenient to define functions without naming them. This is done using **lambda**'​s. For a more detailed discussion regarding lambdas, see the lecture. The following definitions are equivalent:+Functions can be passed as arguments just like any other value value. Also, functions can be returned as parameter. In order to do so, it is convenient to define functions without naming them. This is done using **lambda**'​s. For a more detailed discussion regarding lambdas, see the lecture. The following definitions are equivalent:
  
 <code haskell> <code haskell>
Line 22: Line 16:
 </​code>​ </​code>​
  
-That is the type of ''​f''?​ What is the type of ''​f 5''?​+===== 3.1. String processing =====
  
-47. Consider **sets** represented as characteristic functions with signature ''​s :: Integer -> Bool'',​ where ''​s x'' ​is true if ''​x''​ a member in the setExamples:+The following ​is an input testYou can add more examples to it:
 <code haskell> <code haskell>
-s1 1 True +["​matei@gmail.com",​ "​mihai@gmail.com",​ "​tEst@mail.com",​ "​email@email.com",​ "​short@ax.ro"​] 
-s1 2 = True +</​code>​
-s1 _ = False+
  
-s2 x = x `mod` 2 == True+Use ''​map'',​ ''​foldr''/''​foldl'',​ instead of recursive functions. Wherever possible, use functional composition and closures.
  
-s3 _ = False+3.1.1. Remove uppercases from emails. (Do **not** use recursion). To be able to use character functions from the library, add ''​import Data.Char''​ at the beginning of the program. Use the Internet to find the appropriate character function.
  
-</​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> <code haskell>
-mem :: (Integer ​-> Bool) -> Integer -> Bool +-- write this function as a closure 
-mem ...+rem_upper ​
 </​code>​ </​code>​
  
-48Define the set $math[\{2^n \mid n\in\mathbb{N}\}]+3.1.2. Write a function which removes emails longer than a given size. Write the function as a **functional closure**. Use anonymous functions ​in your implementation,​ then think about how you can replace them by a functional composition of more basic functions. **Hint:** Write your code in steps. Start with the basic idea, then think about how you can write it better and cleaner.
  
-49. Define the set of natural numbers.+<code haskell>​ 
 +longer :: Int -> [String] -> [String] 
 +longer x =  
 +</​code>​
  
-50Implement ​the intersection ​of two sets. Use lambdas.+3.1.3. Count the number ​of emails longer than 12 characters. Use a fold, anonymous functions and functional composition.
 <code haskell> <code haskell>
-intersection :: (Integer -> Bool) -> (Integer -> Bool) -> (Integer -> Bool)+howmany =
 </​code>​ </​code>​
  
-51Write intersection in another way, (without using lambdas). +3.1.4. Split the list between first names and email domains. What ingredients ​(auxiliary functionsare necessary? Use either a fold or a tail-recursive function in your implementation.
 <code haskell> <code haskell>
-intersection' ​:: (Integer ​-> Bool) -> (Integer -> Bool) -> Integer -> Bool+names_emails ​:: [String] ​-> [[String]] 
 +names_emails =
 </​code>​ </​code>​
  
-52Write a function which takes a list of integers, ​and returns ​the set which contains ​them.+3.1.5. Identify the list of the employed domain names (e.g. ''​gmail.com''​). Remove duplicates. Use no recursion ​and no additional prelude function apart from ''​head''​ and ''​tail''​. **Hint** think about the sequence of basic operations you want to perform and assemble ​them using functional composition.
 <code haskell> <code haskell>
-toSet :: [Integer] -> (Integer -> Bool)+domains ​:: [String] -> [String] 
 +domains =
 </​code>​ </​code>​
  
-53Implement ​a function ​which takes a list of sets and computes their intersection.+(!) 3.1.6. In some previous exercise you have, most likely, implemented ​split function ​using ''​foldr''​. Implement one with ''​foldl''​. **Hint:** use an example together with the ''​foldl''​ implementation to figure out what the accumulator should do.
  
 <code haskell> <code haskell>
-capList ​:: [Integer ​-> Bool-> Integer -> Bool+splitl ​:: String ​-> [String] 
 +splitl = 
 </​code>​ </​code>​
  
-+3.1.7. Write a function which extracts the domains from emails, without the dot part. (e.g. ''​gmail''​). Generalise the previous function ''​splitl''​ to ''​splitBy::​ Char -> String -> [String]'',​ and use it each time necessary, in your implementation. **Hint**: Wherever you want to mix pattern matching with guards, start with the patterns first.
-=== Filter ====+
  
-54. Write a function which receives a predicate ''​p ​:: Integer ​-> Bool'',​ a list of integers ''​l'',​ and returns a list of integers from ''​l''​ for which ''​g''​ is true. Your implementation is the ''​filter''​ function from Haskell.+<code haskell>​ 
 +domain ​:: [String] ​-> [String] 
 +domain = 
 +</​code>​
  
 +===== 3.2. A predicate-based implementation for sets =====
 +3.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
  
-55. Solve exercise 24. from [[pp:​l02|Lab ​2]] using ''​filter''​.+s2 x = mod x == 0
  
 +s3 _ = False
  
-56. Test the function ​''​map::(a->b) -> [a] -> [b]''​ from HaskellImplement it.+</​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>​
  
 +3.2.2. Define the set $math[\{2^n \mid n\in\mathbb{N}\}]. ​
  
-57Solve exercise 17from [[pp:​l01|Lab 1]] using ''​map''​.+3.2.3. Define the set of natural numbers.
  
-58Solve exercise 27. from [[pp:​l02|Lab ​2]] using ''​map''​ and ''​filter''​(HintPattern matching can be used in lambdas. Use ''​fst''​ and ''​snd''​ to introspect pairs.)+3.2.4Implement the intersection of two sets. Use lambdas. 
 +<code haskell>​ 
 +intersection :: (Integer -> Bool) -> (Integer -> Bool) -> (Integer -> Bool) 
 +</​code>​
  
-59Solve exercise 31from [[pp:​l02|Lab 2]] using ''​map''​ and ''​filter''​.+3.2.5. Write intersection in another way, (without ​using lambdas).  
 +<code haskell>​ 
 +intersection' ​:: (Integer -> Bool) -> (Integer -> Bool) -> Integer -> Bool 
 +</​code>​
  
-==== Folds ==== +3.2.6. Write a function which takes a list of integers, and returns the set which contains them.
- +
-60. Write a function which appends ​a list of lists of integers:+
 <code haskell> <code haskell>
-app :: [[Integer]] -> [Integer+toSet :: [Integer] -> (Integer ​-> Bool)
 </​code>​ </​code>​
  
-61Write the same function ​tail-recursivelyAre the two functions identical? Why?+3.2.7. Implement a function ​which takes a list of sets and computes their intersection.
  
-62. Implement ''​foldr''​ (see lecture).+<code haskell>​ 
 +capList :: [Integer -> Bool] -> Integer -> Bool 
 +</​code>​
  
-63. Implement ''​foldl'' ​(see lecture).+===== 3.3. Brain twisters ===== 
 +3.3.1. Implement ​''​map''​ using ''​foldl'' ​and ''​foldr''​
  
-64. Implement list concatenation using a fold. +<code haskell> 
- +mapr :: (a -> b) -> [a] -> [b] 
-65. Implement list reversal using fold. +mapl :: (a -> b-> [a] -> [b] 
- +</​code>​
-66. Implement the function from exercise 52 using folds. (Hintthing about what the accumulator should hold) +
- +
-67. Implement exercise 53 using fold.+
  
 +3.3.2. Implement ''​filter''​ using ''​foldl''​ and ''​foldr''​
  
 +<code haskell>
 +filterl :: (a -> Bool) -> [a] -> [a]
 +filterr :: (a -> Bool) -> [a] -> [a]
 +</​code>​
  
 +3.3.3. Implement ''​foldl''​ using ''​foldr''​
 +<code haskell>
 +myfoldl :: (a -> b -> a) -> a -> [b] -> a
 +</​code>​
 +3.3.4. Implement ''​bubbleSort''​. It must use at least one fold
 + <​code haskell>
 +bubbleSort :: [Integer] -> [Integer]
 +</​code>​