====== 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. Functions which //take other functions as parameter// are called **higher-order**. ==== Lambdas ==== 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: f x y = x + y f x = \y -> x + y f = \x -> \y -> x + y f = \x y -> x + y ===== 3.1. String processing ===== The following is an input test. You can add more examples to it: l = ["matei@gmail.com", "mihai@gmail.com", "tEst@mail.com", "email@email.com", "short@ax.ro"] Use ''map'', ''foldr''/''foldl'', instead of recursive functions. Wherever possible, use functional composition and closures. 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. -- write this function as a closure rem_upper = 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. longer :: Int -> [String] -> [String] longer x = 3.1.3. Count the number of emails longer than 12 characters. Use a fold, anonymous functions and functional composition. howmany = 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. names_emails :: [String] -> [[String]] names_emails = 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. domains :: [String] -> [String] domains = (!) 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. splitl :: String -> [String] splitl = 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. domain :: [String] -> [String] domain = ===== 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: s1 1 = True s1 2 = True s1 _ = False s2 x = mod x 2 == 0 s3 _ = False 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: mem :: (Integer -> Bool) -> Integer -> Bool mem = ... 3.2.2. Define the set $math[\{2^n \mid n\in\mathbb{N}\}]. 3.2.3. Define the set of natural numbers. 3.2.4. Implement the intersection of two sets. Use lambdas. intersection :: (Integer -> Bool) -> (Integer -> Bool) -> (Integer -> Bool) 3.2.5. Write intersection in another way, (without using lambdas). intersection' :: (Integer -> Bool) -> (Integer -> Bool) -> Integer -> Bool 3.2.6. Write a function which takes a list of integers, and returns the set which contains them. toSet :: [Integer] -> (Integer -> Bool) 3.2.7. Implement a function which takes a list of sets and computes their intersection. capList :: [Integer -> Bool] -> Integer -> Bool ===== 3.3. Brain twisters ===== 3.3.1. Implement ''map'' using ''foldl'' and ''foldr'' mapr :: (a -> b) -> [a] -> [b] mapl :: (a -> b) -> [a] -> [b] 3.3.2. Implement ''filter'' using ''foldl'' and ''foldr'' filterl :: (a -> Bool) -> [a] -> [a] filterr :: (a -> Bool) -> [a] -> [a] 3.3.3. Implement ''foldl'' using ''foldr'' myfoldl :: (a -> b -> a) -> a -> [b] -> a 3.3.4. Implement ''bubbleSort''. It must use at least one fold bubbleSort :: [Integer] -> [Integer]