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/13 15:48]
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 ====
 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+Functions which //take other functions as parameter// are called **higher-order**. ​
  
-43Define the operator $ from the last lab.+==== Lambdas ==== 
 +Functions can be passed as arguments just like any other value valueAlso, 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 lectureThe following definitions are equivalent:
  
-dollar g x = g x +<code haskell> 
- +f x y = x + y 
-or  +
- +
-g `dollar` x = g x +
- +
- +
-44. Write the type of function composition. +
- +
- +
-45. Define function composition (How to write) +
- +
-comp f g x = f $ g x +
- +
-46. Functions can be passed as parameter just like any value. Also, functions can be returned +
-    as parameter. Lambda. +
- +
-f x y = x + y is the same as:+
 f x = \y -> x + y f x = \y -> x + y
 f = \x -> \y -> x + y f = \x -> \y -> x + y
 f = \x y -> x + y f = \x y -> x + y
 +</​code>​
  
-That is the type of f? +====3.1. String processing ​=====
-What is the type of f 5? +
- +
- +
-47. Consider sets represented as characteristic functions with signature +
-     s :: Integer -> Bool +
- +
-     s x is true if x is in the set. +
- +
-    Write a membership function +
- +
-   mem s x s x +
- +
-   or  +
- +
-   ​mem ​($) +
- +
-48. Write the set {1,2,3} +
-   f 1 True +
-   f 2 True +
-   ​f ​= True +
-   f _ = False +
- +
-49Write the set of natural numbers +
- +
-   f x = x > -1 +
- +
-50Implement the intersection of two sets: +
- +
-union f g \x -> f x && g x +
- +
-51. Write reunion in another way +
- +
-union f g x f x && g x +
- +
-52. Write a function which takes a list of sets, and returns that set  +
- +
-53. (hard) Implement a function which takes a list of sets and computes their intersection +
- +
-f [s] +
-f (s:​xs) ​\x -> s x && (f xs) x +
- +
- +
- +
-54. Write a function which receives a g :: Integer -> Bool, a list of integers, +
-    and returns a list of integers for which g is true. +
- +
-filter p [] [] +
-filter p (x:xs) +
- | p x == True = x:(filter p xs) +
- | otherwise = filter p xs +
- +
-55. Solve exercise 22. using filter+
  
-filter (>0)+The following is an input test. You can add more examples to it: 
 +<code haskell>​ 
 +["​matei@gmail.com",​ "​mihai@gmail.com",​ "​tEst@mail.com",​ "​email@email.com",​ "​short@ax.ro"​] 
 +</code>
  
-56. Implement ​map+Use ''​map'',​ ''​foldr''/''​foldl'',​ instead of recursive functions. Wherever possible, use functional composition and closures.
  
-57Solve exercise 15using map:+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.
  
-f = map g +<code haskell> 
- where g True 1 +-- write this function as a closure 
-       g False = 0+rem_upper ​=  
 +</​code>​
  
-58Solve exercise 25using map and filter: +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 ideathen think about how you can write it better and cleaner.
-Let f "​321CB"​ [("​321CB"​["​Matei",​ "​Andrei",​ "​Mihai"​]),​ ("​322CB",​["​George,​ Matei"​])] +
-  = ["​Matei",​ "​Mihai"​]+
  
-  (Hint. Pattern matching can be used in lambdas. Use fst and snd on pairs)+<code haskell>​ 
 +longer :: Int -> [String] -> [String] 
 +longer x =  
 +</​code>​
  
-f x l = (filter (\(c:_)-== '​M'​)) $ snd $ head $ (filter (\(f,_)-f==x)) l+3.1.3. Count the number of emails longer than 12 characters. Use a fold, anonymous functions and functional composition. 
 +<code haskell> 
 +howmany ​= 
 +</code>
  
-or+3.1.4. Split the list between first names and email domains. What ingredients (auxiliary functions) are necessary? Use either a fold or a tail-recursive function in your implementation. 
 +<code haskell>​ 
 +names_emails :: [String] -> [[String]] 
 +names_emails = 
 +</​code>​
  
-f x = (filter (\(c:_)-> c == 'M')) . snd . head . (filter (\(f,_)-> f==x)) +3.1.5. Identify the list of the employed domain names (e.g. ''​gmail.com''​). ​Remove duplicatesUse 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>​ 
 +domains :: [String] ​-> [String] 
 +domains ​= 
 +</​code>​
  
-59Solve exercise 29. using map and filter+(!) 3.1.6. In some previous exercise you have, most likely, implemented a 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.
  
-    f [("Dan Matei Popovici",​9),​("​Mihai",​4),​("​Andrei Alex",​6)] = +<code haskell>​ 
-    ​ [(["​Dan",​ "​Matei",​ "​Popovici"​],​10),​(["​Andrei,​Alex"​],​6)]+splitl :: String -> [String] 
 +splitl ​=  
 +</​code>​
  
-f = bonus splall ​rem +3.1.7Write a function which extracts the domains from emailswithout 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.
- where +
- rem = filter (\(_,y) -> y > 4) +
- splall = map (\(x,y) -> (spl x,y)) +
- bonus = map (\(l,​y) ​-> if length l == 3 then (l,y+1) else (l,y)) +
- spl [] [] rest = rest +
-  spl [] w rest = w:rest +
-  spl (x:xs) w rest  +
- ​  ​ | x == ' ' ​= spl xs [] (w:rest) +
- ​  ​ | otherwise = spl xs (x:w) rest +
  
 +<code haskell>
 +domain :: [String] -> [String]
 +domain =
 +</​code>​
  
-60Write function which appends a list of lists:+===== 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'' ​member in the set. Examples: 
 +<code haskell>​ 
 +s1 1 = True 
 +s1 2 = True 
 +s1 _ = False
  
-f [] = [] +s2 x = mod 2 == 0
-f (x:xs) = x ++ (f xs)+
  
-61. Write the same function tail-recursively+s3 _ = False
  
-[] acc = acc +</​code>​ 
-f (x:xs) acc = f xs (x++acc)+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>​
  
-Are the two functions identical? Why?+3.2.2. Define ​the set $math[\{2^n \mid n\in\mathbb{N}\}]. ​
  
-62Implement foldr+3.2.3. Define the set of natural numbers.
  
-63. Implement ​foldl+3.2.4. Implement ​the intersection of two sets. Use lambdas. 
 +<code haskell>​ 
 +intersection :: (Integer -> Bool) -> (Integer -> Bool) -> (Integer -> Bool) 
 +</​code>​
  
-64Implement concatenation ​using a fold: +3.2.5. Write intersection in another way, (without ​using lambdas). ​ 
-  app l1 l2 = foldr (:) l2 l1+<code haskell>​ 
 +intersection' ​:: (Integer -> Bool-> (Integer -> Bool) -> Integer -> Bool 
 +</​code>​
  
-65Implement reversal using fold: +3.2.6. Write function which takes a list of integers, and returns the set which contains them. 
-  rev = foldl (\x y->y:x) []+<code haskell> 
 +toSet :: [Integer-> (Integer -> Bool) 
 +</​code>​
  
-66.(hard) ​Implement ​the string-splitting ​function ​from exercise 46 using folds: +3.2.7. Implement ​function ​which takes a list of sets and computes their intersection.
-    (Hint: thing about what the accumulator should hold)+
  
-(Note for TAsignature needed. Discussion for later)+<code haskell>​ 
 +capList ​:: [Integer -> Bool] -> Integer -> Bool 
 +</​code>​
  
-spl :: String -> [String] +===== 3.3. Brain twisters ===== 
-spl foldr op [""​] +3.3.1. Implement ​''​map'' ​using ''​foldl''​ and ''​foldr''​
-        where op ' ' (l:​rest) ​[]:l:rest +
-              op c (l:​rest) ​(c:​l):​rest +
-   ​ +
-67. Implement ​exercise 47 using fold:+
  
-f (s:xs= foldr (\s acc x-> s x && acc xs xs+<code haskell>​ 
 +mapr :: (a -> b-> [a] -> [b] 
 +mapl :: (-> b-> [a] -> [b] 
 +</​code>​
  
 +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>​