You are on page 1of 2

Prof.aa Dr. J. Giesl Notes: Please solve these exercises in groups of two!

Functional Programming SS12 Exercise Sheet 3 (due 09.05.2012) M. Brockschmidt, F. Emmes

The solutions must be handed in directly before (very latest: at the beginning of ) the exercise course on Wednesday, 09.05.2012, 11:45, in lecture hall AH 2. Alternatively you can drop your solutions into a box which is located right next to Prof. Giesls oce (until the exercise course starts). Please write the names and immatriculation numbers of all (two) students on your solution. Also please staple the individual sheets!

Exercise 1 (Higher-order data):

(1 + 2 + 3 + 2 + 2 = 10 points)

In this exercise, we consider an alternative to the representation of polynomials presented on exercise sheet 2. Here, we use the following data type: data Expr = Operator ( Int -> Int -> Int ) Expr Expr | Variable String | Constant Int You can visualize a term of type Expr like t =Operator (*) (Operator (+) (Variable "x") (Constant 2)) (Constant 3) as a tree as follows: (*)

(+)

"x"

Here, each Operator node contains a function that describes how the values of its two children should be combined. a) To instantiate variables in a term of type Expr, we want to use substitutions as dened by type Substitution = String -> Int. Implement a function baseSubstitution :: Substitution such that every variable is mapped to 0. So for instance, baseSubstitution "x" returns 0. b) To build more complex substitutions, the function extendSubstitution :: Substitution -> String -> Int -> Substitution should be used. It takes an existing substition, a String s and an Int i, and returns a new substitution that maps s to i and otherwise behaves like the old substitution. For example, extendSubstitution baseSubstitution "x" 12 should return a substitution that maps "x" to 12 and every other String to 0. c) We now want to implement a fold function for Expr terms:
foldExpr :: ((Int -> Int -> Int) -> a -> a -> a) -> (String -> a) -> (Int -> a) -> Expr -> a

Analogously to other fold functions, foldExpr f g h e should yield a term in which every occurrence of Operator is replaced by f, every Variable by g, and every Constant by h. For example,
getVars = foldExpr (\_ l r -> l ++ r) (\s -> [s]) (\_ -> [])

should compute a list containing all variables of an Expr term, i.e., applied to t from above, it should yield ["x"].

Functional Programming SS12 Exercise Sheet 3 (due 09.05.2012) d) Implement a function countOperators :: Expr -> Int that counts how many Operator constructors occur in an Expr term. For example, for t from above, it should yield 2. Use foldExpr from part c). e) Finally, we want to evaluate terms of type Expr using a function evalExpr :: Substitution -> Expr -> Int. To evaluate evalExpr sub t, every variable in the term t should be instantiated as specied by sub. Then, all functions in Operator nodes should be applied to the (evaluated) subexpressions. For example, when evaluating the term t from above, with "x" instantiated by 12, the result should be 42. Use foldExpr from part c).

Exercise 2 (Higher-order functions):

(1 + 1 + 2 + 2 + 2 + 2 = 10 points)

a) Implement a function conjunction :: [Bool] -> Bool. For an input list [b1 , b2 , . . . , bn ], conjunction returns True if all of the values [b1 , b2 , . . . , bn ] are True, i.e., if b1 b2 . . . bn is true. Do not use explicit recursion, but foldr. b) Implement a function universalQ :: (a -> Bool) -> [a] -> Bool that determines whether the property encoded by the rst argument holds for all elements of the list passed as second argument. For example, universalQ even list should yield True if all elements of list are even numbers. Do not use explicit recursion, but conjunction and map. c) Implement a function sortUsing :: (a -> a -> Bool) -> [a] -> [a] that sorts a list using a custom comparison function supplied by the user. If we have two elements x, y and the comparison function c returns True for c x y, then x should occur before y in the sorted list. For example, sortUsing (>) [1,2,3,4] should yield [4,3,2,1]. In this part of the exercise (and also in parts d)f )) you may use explicit recursion. d) Implement a function removeWhile :: (a -> Bool) -> [a] -> [a] that removes elements from the input list as long as the predicate given as rst argument is True for these elements. For example, removeWhile even [2,4,1,4] should yield [1,4]. e) Implement a function meld :: (a -> a -> b) -> [a] -> [b] that applies a function to every two consecutive elements in a list and returns a list containing the results. For example meld (+) [1, 2, 3, 4] = [3, 5, 7]. For lists xs with less than two elements, meld f xs returns []. f ) Implement a function partition :: (a -> Bool) -> [a] -> ([a], [a]) that gets a function f and a list l and splits the elements of l into two separate lists, such that the rst contains only the elements for which f returns True and the second contains only the elements for which f returns False. For example partition (\x -> x mod 2 == 0) [1,2,3,4,5] = ([2,4],[1,3,5]).