Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Exercise 1 (4 + 3 + 4 + 5 + 6 22 Points)

Download as pdf or txt
Download as pdf or txt
You are on page 1of 10

First name

Last name

Matriculation number 1

Exercise 1 (4 + 3 + 4 + 5 + 6 = 22 points)
The following data structure represents polymorphic lists that can contain values of two types in arbitrary order: data DuoList a b = C a (DuoList a b) | D b (DuoList a b) | E Consider the following list zs of integers and characters: [ 4, a , b , 6 ] The representation of zs as an object of type DuoList Int Char in Haskell would be: C 4 (D a (D b (C 6 E))) Implement the following functions in Haskell. (a) The function foldDuo of type (a -> c -> c) -> (b -> c -> c) -> c -> DuoList a b -> c works as follows: foldDuo f g h xs replaces all occurrences of the constructor C in the list xs by f, it replaces all occurrences of the constructor D in xs by g, and it replaces all occurrences of the constructor E in xs by h. So for the list zs above, foldDuo (*) (\x y -> y) 3 zs should compute (*) 4 ((\x y -> y) a ((\x y -> y) b ((*) 6 3))), which in the end results in 72. Here, C is replaced by (*), D is replaced by (\x y -> y), and E is replaced by 3.

foldDuo f g h (C x xs) foldDuo f g h (D x xs) foldDuo f g h E

= f x (foldDuo f g h xs) = g x (foldDuo f g h xs) = h

First name

Last name

Matriculation number 2

(b) Use the foldDuo function from (a) to implement the cd function which has the type DuoList Int a -> Int and returns the sum of the entries under the data constructor C and of the number of elements built with the data constructor D. In our example above, the call cd zs should have the result 12. The reason is that zs contains the entries 4 and 6 under the constructor C and it contains two elements a and b built with the data constructor D.

cd = foldDuo (+) (\x y -> y + 1) 0

First name

Last name

Matriculation number 3

(c) Consider the following data type declaration for natural numbers: data Nats = Zero | Succ Nats A graphical representation of the rst four levels of the domain for Nats could look like this: Succ (Succ Zero) Succ (Succ (Succ ))
ii iiii i i i iii iiii

Succ Zero Zero Succ

Succ (Succ )

l lll lll l l ll lll

q qqq q q qqq qqq

We dene the following data type Single, which has only one data constructor One: data Single = One Sketch a graphical representation of the rst three levels of the domain for the data type DuoList Bool Single.

BB BB BB BB BB C False Q QQQ BBB QQQ BB QQQ BB QQ B

C True B

C (C )

D (C ) D (D ) D One@ @@ z z zz @ @@ zz zz z z @@ zz zz @@ zz zz @ z z @@ zz zz lC E lD E @@ zz lllll zz lllll @ z z @@ z llll zz llll @ zzz lll zzlll E C RR gg D RRR ggggg g g g RRR g gggg RRR ggggg RRR R gggggggg

C (D )

First name

Last name

Matriculation number 4

(d) Write a Haskell function printLength that rst reads a line from the user, then prints this string on the console and in the end also prints the length of this string on the console. Also give the type declaration for your function. You may use the do-notation, but you are not obliged to use it. Some of the following pre-dened functions can be helpful: getLine :: IO String reads a line from the user length :: String -> Int has the length of a string as its result show :: Int -> String converts a number to a string putStr :: String -> IO () writes a string to the console An example run should look as given below. Here the string foo was read from the user. Main> printLength foo foo3 -- without do-notation printLength :: IO () printLength = getLine >>= \s -> putStr s >> putStr (show (length s)) -- alternative: with do-notation printLength2 :: IO () printLength2 = do s <- getLine putStr s putStr (show (length s))

First name

Last name

Matriculation number 5

(e) The digit sum of a natural number is the sum of all digits of its decimal representation. For example, the digit sum of the number 6042 is 6 + 0 + 4 + 2 = 12. Write a Haskell function digitSum :: Int -> Int that takes a natural number and returns its digit sum. Your function may behave arbitrarily on negative numbers. It can be helpful to use the pre-dened functions div, mod :: Int -> Int -> Int to compute result and remainder of division, respectively. For example, div 7 3 is 2 and mod 7 3 is 1. digitSum :: Int -> Int digitSum 0 = 0 digitSum (n+1) = mod (n+1) 10 + digitSum (div (n+1) 10)

Now implement a function digitSumList :: Int -> Int -> [Int] where digitSumList n b returns a list of all those numbers x where 0 x b and where the digit sum of x is n. Perform your implementation only with the help of a list comprehension, i.e., you should use exactly one declaration of the following form: digitSumList ... = [ ... | ... ] Of course, here you can (and should) make use of the function digitSum to compute the digit sum of a number. digitSumList :: Int -> Int -> [Int] digitSumList n b = [ x | x <- [0..b], digitSum x == n ]

First name

Last name

Matriculation number 6

Exercise 2 (4 + 5 = 9 points)
Consider the following Haskell declarations for the square function: square :: Int -> Int square 0 = 0 square (x+1) = 1 + 2*x + square x (a) Please give the Haskell declarations for the higher-order function f square corresponding to square, i.e., the higher-order function f square such that the least xpoint of f square is square. In addition to the function declaration(s), please also give the type declaration of f square. Since you may use full Haskell for f square, you do not need to translate square into simple Haskell.

f square :: (Int -> Int) -> (Int -> Int) f square square 0 = 0 f square square (x+1) = 1 + 2*x + square x

(b) We add the Haskell declaration bot = bot. For each n N please determine which function is computed by f squaren bot. Here f squaren bot represents the n-fold application of f square to bot, i.e., it is short for f square (f square . . . (f square bot) . . .).
n times

Let fn : Z Z be the function that is computed by f squaren bot. Give fn in closed form, i.e., using a non-recursive denition.

(f squaren ())(x) =

x2 , if 0 x < n , otherwise

First name

Last name

Matriculation number 7

Exercise 3 (6 points)
Let D1 , D2 be domains, let D2 be a complete partial order on D2 . As we know from the lecture, then also D1 D2 is a complete partial order on the set of all functions from D1 to D2 . Prove that D1 D2 is also a complete partial order on the set of all constant functions from D1 to D2 . A function f : D1 D2 is called constant i f (x) = f (y ) holds for all x, y D1 . Hint: The following lemma may be helpful: If S is a chain of functions from D1 to D2 , then S is the function with: (S )(x) = {f (x) | f S }

We need to show two statements: a) The set of all constant functions from D1 to D2 has a smallest element . Obviously, the constant function f with f (x) = for all x D1 satises this requirement. b) For every chain S on the set of all constant functions from D1 to D2 there is a least upper bound S which is an element of the set of all constant functions from D1 to D2 . Let S be a chain of constant functions from D1 to D2 . By the above lemma, we have (S )(x) = {f (x) | f S }. It remains to show that the function S : D1 D2 actually is a constant function. For all x, y D1 , we have: (S )(x) = {f (x) | f S } = {f (y ) | f S } = (S )(y )

since the elements of S are constant functions

Therefore, also (S )(x) is a constant function.

First name

Last name

Matriculation number 8

Exercise 4 (4 + 5 = 9 points)
Consider the following data structure for polymorphic lists: data List a = Nil | Cons a (List a) (a) Please translate the following Haskell-expression into an equivalent lambda term (e.g., using Lam). Recall that pre-dened functions like even are translated into constants of the lambda calculus. It suces to give the result of the transformation. let f = \x -> if (even x) then Nil else Cons x (f x) in f

(fix (f x. if (even x) Nil (Cons x (f x)) ) )

First name

Last name

Matriculation number 9

(b) Let be the set of rules for evaluating the lambda terms resulting from Haskell, i.e., contains at least the following rules: fix f. f (fix f ) plus 2 3 5 Now let the lambda term t be dened as follows: t = (fix (g x. Cons (plus x 3) Nil)) 2 Please reduce the lambda term t by WHNO-reduction with the -relation. You have to give all intermediate steps until you reach weak head normal form (and no further steps).

(fix (g x. Cons (plus x 3) Nil)) 2 ((f. f (fix f )) (g x. Cons (plus x 3) Nil)) 2 ((g x. Cons (plus x 3) Nil) (fix (g x. Cons (plus x 3) Nil))) 2 ((x. Cons (plus x 3) Nil) 2 Cons (plus 2 3) Nil

First name

Last name

Matriculation number 10

Exercise 5 (10 points)


Use the type inference algorithm W to determine the most general type of the following lambda term under the initial type assumption A0 . Show the results of all sub-computations and unications, too. If the term is not well typed, show how and why the W -algorithm detects this. f. (Succ (f x)) The initial type assumption A0 contains at least the following: A0 (Succ) = (Nats Nats) A0 (f ) = a. a A0 (x) = a. a

W (A0 , f. (Succ (f x)) ) W (A0 + {f :: b1 }, (Succ (f x)) ) W (A0 + {f :: b1 }, Succ) = (id, (Nats Nats) ) W (A0 + {f :: b1 }, (f x) ) W (A0 + {f :: b1 }, f ) = (id, b1 ) W (A0 + {f :: b1 }, x) = (id, b2 ) mgu(b1 , (b2 b3 ) ) = [b1 /(b2 b3 )] = ([b1 /(b2 b3 )], b3 ) mgu((Nats Nats), (b3 b4 ) ) = [b3 /Nats, b4 /Nats] = ([b1 /(b2 Nats), b3 /Nats, b4 /Nats], Nats) = ([b1 /(b2 Nats), b3 /Nats, b4 /Nats], ((b2 Nats) Nats) )

Resulting type: ((b2 Nats) Nats)

You might also like