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 16:50]
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**. ​
  
-43Define the operator ''​($)''​ from [[pp:​l02|Lab 2]] as a higher-order function.+==== 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 themThis is done using **lambda**'​s. For a more detailed discussion regarding lambdas, see the lecture. The 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>​