Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
pp:l02 [2020/03/12 14:40] pdmatei |
pp:l02 [2021/03/16 19:24] (current) roxana_elena.stiuca [2.3. Strings in Haskell] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Pattern matching and basic types in Haskell ====== | + | ====== 2. Pattern matching and basic types in Haskell ====== |
- | 21. Extract the fourth element from a list of integers: | + | ===== 2.1. Pattern matching ===== |
- | f l = head (tail (tail (tail l)))) | + | It is likely that in the above implementations you used ''head'' and ''tail'', or branch definitions combined with '_' to solve the exercises. Haskell supports a more elegant means of //value introspection//, called **pattern matching**. For instance, in: |
- | 22. Write the same function which returns 0 if the list contains less that four elements. | + | <code haskell> |
+ | f [] = ... | ||
+ | f (h:t) = ... | ||
+ | </code> | ||
- | f [] = 0 | + | ''(h:t)'' is a **pattern** which denotes a non-empty list where ''h'' is the first element and ''t'' is the rest of the list. In fact, ''[]'' is also a pattern denoting the empty lists. Patterns are **allways** surrounded by round parentheses. They can also be composite, as in the exercise below: |
- | f [_] = 0 | + | |
- | f [_,_] = 0 | + | |
- | f [_,_,_] = 0 | + | |
- | f l = head (tail (tail (tail l)))) | + | |
- | 23. In Haskell, one can use patterns to examine the contents of lists, pairs and other dataypes. | + | 2.1.1. Write a function which returns the number of elements from a list. Use patterns. |
- | f (x:y:z:w:l) = w | + | 2.1.2. Write a function which takes a list of integer lists, and concatenates them. (E.g. ''f [ [1,2,3],[4,5] ] = [1,2,3,4,5]''). |
- | f _ = 0 | + | |
+ | 2.1.3 (!) Write the **same** function, this time using only the **cons** ('':'') operator as well as **patterns**. | ||
- | What types have x,y,z,w ? What type does have l ? | + | 2.1.4. Write a function which removes duplicates from a list of integers. |
- | What about: | + | ===== 2.2. Types in Haskell ===== |
+ | 2.2.1. What are the types of ''x,y,z,w'' and that of ''l'' in the implementation below? | ||
+ | <code haskell> | ||
f (x:y:z:w:l) = w | f (x:y:z:w:l) = w | ||
+ | f _ = 0 | ||
+ | </code> | ||
- | What is the difference? | + | How about: |
+ | <code haskell> | ||
+ | f (x:y:z:w:l) = w | ||
+ | </code> | ||
+ | What is the difference? | ||
| | ||
- | 24. Write a function which filters out all negative numbers: | + | 2.2.2. What is the type of the function: |
- | + | <code haskell> | |
- | f [] = [] | + | |
- | f (x:xs) = | + | |
- | | x > 0 = x:(f xs) | + | |
- | | otherwise = f xs | + | |
- | + | ||
- | 25. What is the type of the function: | + | |
f x y = (x,y) | f x y = (x,y) | ||
+ | </code> | ||
- | [[discussion on pairs]] f :: a -> b -> (a,b) | + | In the body of a function definition, '','' is a **base constructor** for pairs. The following are pairs: ''(1,2), ("Matei",20), ([1,2],3)''. Note that there is no restriction on the type of the first and second values of a pair. |
- | + | ||
- | 26. What is the type of the function: | + | |
+ | 2.2.3. What is the type of the function: | ||
+ | <code haskell> | ||
f 'a' _ = [] | f 'a' _ = [] | ||
f x y = x:y | f x y = x:y | ||
+ | </code> | ||
- | [[discussion on strings]] f :: Char -> String -> String | + | In Haskell, the type ''String'' is equivalent to ''[Char]'' (hence strings are lists of chars). Strings can be introspected using patterns just like any other list. |
+ | 2.2.4. Let f be the function below: | ||
+ | <code haskell> | ||
+ | f "321CB" [("321CB", ["Matei", "Andrei", "Mihai"]), ("322CB",["George", "Matei"])] = ["Matei", "Mihai"] | ||
+ | </code> | ||
- | 27. Let f "321CB" [("321CB", ["Matei", "Andrei", "Mihai"]), ("322CB",["George, Matei"])] | + | What is the signature of ''f''? |
- | = ["Matei", "Mihai"] | + | |
- | What is the signature of f? | ||
- | f :: String -> [(String,[String])] -> [String] | ||
- | What does f do? | + | ===== 2.3. Strings in Haskell ===== |
- | Write an implementation for f: | + | 2.3.1. Write a function which takes a list of words and makes the first letter of each word uppercase. |
- | f x [] = [] | + | 2.3.2. Write a function which takes a list of words and makes **all** letters uppercase. |
- | f x ((y,l):ys) | + | |
- | | x == y = getM l | + | |
- | | otherwise = f x ys | + | |
- | where | + | |
- | getM [] = [] | + | |
- | getM ((x:l):xs) | + | |
- | | x == 'M' = (x:l):(getM xs) | + | |
- | | otherwise = getM xs | + | |
- | 28. Write a function which returns true if the third largest element from a list is positive | + | 2.3.3. (!) Write a function which takes a text and a pattern and returns the number of occurrences of the pattern in the text. |
+ | Example: | ||
+ | <code haskell> | ||
+ | search "I eat green apples" "eat" = 1 | ||
+ | search "ababaab" "aba" = 2 | ||
+ | </code> | ||
- | f l = g (reverse (sort l)) | + | 2.3.4. (!) What does ''f'', defined in exercise 2.2.4., do (note that ''Matei'' and ''Mihai'' both start with letter 'M')? Write an implementation for ''f''. |
- | where g (x:y:z:_) = | + | |
- | | z > 0 = True | + | |
- | | otherwise = False | + | |
- | g _ = False | + | |
- | 29. Sometimes it really helps to define function via function composition. For instance: | + | 2.3.5. Write the signature and implement the following function: |
+ | <code haskell> | ||
+ | f ["Matei", "Mihai"] ["Popovici","Dumitru"] = [("Matei","Popovici"), ("Mihai","Dumitru")] | ||
+ | </code> | ||
- | f x = (g.h) x | + | 2.3.6. Implement the following function: |
- | where g x = 2*x | + | <code haskell> |
- | h x = x + 1 | + | f ["Matei", "Mihai"] ["Popovici","Dumitru"] = ["MPopovici", "MDumitru"] |
- | + | </code> | |
- | What type does f have? | + | |
- | What type does g have? | + | |
- | + | ||
- | What does the following function do? | + | |
- | + | ||
- | f x = ff x | + | |
- | where g x = 2*x | + | |
- | h x = x + 1 | + | |
- | ff = f.h | + | |
- | + | ||
- | What does the following function do? | + | |
- | + | ||
- | f x = ff x | + | |
- | where g x = 2*x | + | |
- | h x = x + 1 | + | |
- | ff = h.f | + | |
- | + | ||
- | + | ||
- | + | ||
- | 30. Rewrite exercise 28 via function composition: | + | |
- | + | ||
- | f l = (g . reverse . sort) l | + | |
- | where ... | + | |
- | + | ||
- | + | ||
- | 31.(hard) Write a function which takes a list of pairs - student-name and grade, removes | + | |
- | those with grades <5, splits the name in substrings, and adds one point bonus to | + | |
- | people with three names: | + | |
+ | 2.3.7. Write a function which takes a list of pairs - student-name and grade, removes those with grades less than 5, splits the name in substrings, and adds one bonus point to people with three names. Example: | ||
+ | <code haskell> | ||
f [("Dan Matei Popovici",9),("Mihai",4),("Andrei Alex",6)] = | f [("Dan Matei Popovici",9),("Mihai",4),("Andrei Alex",6)] = | ||
- | [(["Dan", "Matei", "Popovici"],10),(["Andrei,Alex"],6)] | + | [(["Dan", "Matei", "Popovici"],10),(["Andrei", "Alex"],6)] |
- | + | </code> | |
- | f l = (bonus . splall . rem) l | + | |
- | where rem [] = [] | + | |
- | rem ((s,x):xs) | + | |
- | | x < 5 = rem xs | + | |
- | | otherwise = (s,x):(rem xs) | + | |
- | spl [] [] rest = rest | + | |
- | spl [] w rest = w:rest | + | |
- | spl (x:xs) w rest | + | |
- | | x == ' ' = spl xs [] (w:rest) | + | |
- | | otherwise = spl xs (x:w) rest | + | |
- | splall [] = [] | + | |
- | splall ((s,x):xs) = ((spl s),x):(splall xs) | + | |
- | bonus [] = [] | + | |
- | bonus ((l,x):xs) | + | |
- | | (length l) == 3 = (l,x+1):(bonus xs) | + | |
- | | otherwise = (l,x):(bonus xs) | + | |
- | + | ||
- | 32. Write the signature and implement the following function: | + | |
- | + | ||
- | f ["Matei", "Mihai"] ["Popovici"] ["Dumitru"] = [("Matei","Popovici"), ("Mihai","Dumitru")] | + | |
- | + | ||
- | f :: [String] -> [String] -> [(String,String)] | + | |
- | f (x:xs) (y:ys) = (x,y):(f xs ys) | + | |
- | + | ||
- | 33. Implement the following function: | + | |
- | + | ||
- | f ["Matei", "Mihai"] ["Popovici"] ["Dumitru"] = ["MPopovici", "MDumitru"] | + | |
- | + | ||
- | f (((c:_):xs)) (y:ys) = (c:y):(f xs ys) | + | |
- | + | ||
- | 34. Sometimes it helps to use functions in infix form. For instance: | + | |
- | + | ||
- | instead of mod x 2, we can write x `mode` 2. We can also define functions infix: | + | |
- | + | ||
- | x `f` y = x + y | + | |
- | + | ||
- | Implement an abbreviation function for exercise 31 and use it infix: | + | |
- | + | ||
- | f (x:ys) (y:ys) = (x `conc` y):(f xs ys) | + | |
- | where (x:_) `conc` s = x:s | + | |
- | + | ||
- | 35. Just in the same way, we can treat infix functions as prefix. | + | |
- | :t (+) | + | |
- | :t (&&) | + | |
- | :t (++) | + | |
- | + | ||
- | 36. What about function composition? Is it a special operator, or is it just a function as well? | + | |
- | + | ||
- | :t (.) | + | |
- | + | ||
- | 37. What does the function below do? | + | |
- | + | ||
- | f l = (((++) "?").((:) '>')) l | + | |
- | + | ||
- | + | ||
- | How about? | + | |
- | + | ||
- | f = (((:) '>').(++"?")) | + | |
- | + | ||
- | 38. Write a function of a single line, such that: | + | |
- | + | ||
- | f "Matei" = "[Matei]" | + | |
- | + | ||
- | f = ("["++).(++"]") | + | |
- | + | ||
- | 39. Use only (:) to solve exercise 38 | + | |
- | + | ||
- | f = ((:) '[') . reverse . ((:) ']') . reverse | + | |
- | + | ||
- | 40. What does the function ($) to? | + | |
- | (Use :t, and make up some tests) | + | |
- | + | ||
- | 41. Write the following implementation using only ($): | + | |
- | + | ||
- | f "||" "Matei" = "||Matei||" | + | |
- | f s l = (s++) $ h $ (++s) $ reverse l | ||
- | 42. Solve exercise 13. from [[Lab 2 | pp:l02]] using $ and other improvements (treat the case when the list has | ||
- | fewer elements): | ||
- | f l = g $ reverse l | ||
- | where g (_:_:x:_) = not $ x `mod` 2 | ||
- | g _ = False |