Example Answers

Questions and answers to Examples in Functional Programming in Clean, Part I. Give multiple answers to any one question, if deemed helpful or novel. Comment code if necessary.

To make a blue "source code box", indent each line of code one space, and use  at the end of completed lines to make breaks ("carriage returns"); otherwise, everything runs together.

Chapter 1
1 Make sure the CLEAN system is installed on your computer. The system can be downloaded from http://www.cs.kun.nl/~clean. Write and execute a program that prints the value 42.

2 Write a function that takes two arguments, say n and x, and computes their power, x^n. Use this to construct a function that squares its argument. Write a program that computes the square of 128.

3 Define the function isum :: Int -> Int which adds the digits of its argument. So, isum 1234 = 10 isum 0 = 0 isum 1001 = 2 You may assume that isum is applied to an argument which is not negative.

4 Use the function isum to check whether a number can be divided by 9.

5 Define a function Max with two arguments that delivers the maximum of the two.

6 Define a function Min that has two arguments that delivers the minimum of the two.

7 Define a function MaxOfList that calculates the largest element of a list.

8 Define a function MinOfList that calculates the smallest element of a list.

9 Define a function Last that returns the last element of a list.

10 Define a function LastTwo that returns the last two elements of a list.

11 Define a function Reverse that reverses the elements in a list.

12 Define a function Palindrome which checks whether a list of characters is a palindrome, i.e. when you reverse the characters you should get the same list as the original.

Chapter 2
1 Combining operators. Define the function odd using the operators isEven, + and o.

2 Finite precision of reals. Execute the second start expression given in section 2.4.2. Rewrite the program such that it only prints the smallest number that is different from zero using the function until.

3 Counting days. Write a function that given the current day and your date of birth determines how many days you have to wait for your birthday.

4 Define the function mapfun that applies a list of functions to its second argument returning the results of these function applications into a list. So, e.g. mapfun [f,g,h] x = [f x, g x, h x]

Chapter 3
1 Define a function CountOccurrences that counts the number of times a given element is occurring in a given list. CountOccurrences :: a [a] -> Int | == a

2 Define the function MakeFrequenceTable MakeFrequenceTable [a] -> [(a, Int)] | == a That makes a frequency table. The table consists of a list of tuples. Each tuple consists of an element from the original list and its frequency (percentage). E.g. Frequencytable [1,2,3,2] = [(1,25),(2,50),(3,25)]

3 Equality on tuples can be defined as: (==) (a,b) (c,d) = a == c && b == d Although the equality operator is also applied in the right-hand side expression this function is actually not recursive.

What is the difference between this operator definition and the recursive definition of equality for lists in Section 3.1.2?

4 Define the function flatten (see Section 3.1.2) in terms of foldr and ++.

5 Write a list comprehension for generating all permutations of some input list.

6 Describe the effect on the evaluation order of swapping x==y and xs==ys in the definition of == in Section 3.2.2.

7 Extend the set of operators on rational numbers with == and <.

8 Discuss how you can guarantee that rational numbers used in ordinary programs are always 'simplified'.

9 Define an appropriate data type for AVL-trees and define functions for balancing, searching, inserting and deleting elements in such trees.

10 Proof that abs (sign x) < 2 for all x using: sign x | x < 0 = -1 | x == 0 = 0 | x > 0 = 1

11 Proof that fib n � n for all n�2.

12 Proof that l ++ [] = l.

13 Proof that x ++ (y ++ z) = (x ++ y) ++ z. This is the associativity of ++.

14 Proof that rev (x ++ y) = rev y ++ rev x.

15 Proof that rev (rev xs) = xs for every finite list.

16 Proof that foldl (\xs x = [x:xs]) ys x = foldl (\xs x = [x:xs]) [] x ++ ys.

17 Synthesize a recursive function to add elements of a list which is equivalent to: sum :: [t] -> t | +, zero t sum l = foldr (+) zero l

18 Design a Eureka rule to introduce an accumulator and transform the recursive function to a call of the addition function using the accumulator.

Chapter 4
1 Define an instance for type Q of the standard class Arith. class Arith a | PlusMin, MultDiv, abs, sign, ~ a

2 Define complex numbers similar to Q and specify an instance of the class Arith for this new type.

3 Define an instance of PlusMin for lists [a] such that, for instance, the addition of two lists takes place element wise (if necessary, the shortest list is extended with zeros to obtain two lists of equal length). So, [1,2,3] + [4,5] = [5,7,3].

4 Why should a Pipe object contain at least one function (each Pipe object ends with a Direct constructor containing the final function to be applied)? One can image a definition of Pipe with a kind of Nil constructor with no argument as a terminator.

Chapter 5
1 Write a program that applies a given transformation function from character lists to character lists on a given file. Structure the program such that the transformation function can be provided as an argument. Test the program with a function that transforms normal characters into capitals and with a function that collects lines, sorts them and concatenates them again to a character list.

2 Combine the FileReadDialog and FileWriteDialog functions into a complete copyfile program which copies files repeatedly as indicated in a dialog by the user.

3 Adapt the program you made for exercise 5.1 such that it transforms files as indicated in a dialog by the user.

4 Write a program that generates one of the following curves in a window: or

5 Adapt the display file program such that the user can save the viewed file with a SelectOutputFile dialog. Use (possibly a variant of) the function FileWriteDialog. In order to assure that saving is done instantly instead of lazily the Files component of the ProgState can be made strict by prefixing Files in the type definition of ProgState with an exclamation mark. Add the text as a field in the state record. It may also prove to be useful to add the name of the file and the file itself to this state. In order to allow the user to overwrite the displayed file the program will have to be changed to use fopen for displaying instead of sfopen since a file opened with sfopen can be neither updated nor closed.

6 Adapt the program you made for exercise 5.3 such that it shows the result of a transformation of a file in a window such that the user can browse through it before saving it.

7 Include in the program of exercise 5.6 a menu function opening a dialog with RadioItems such that the user can select the transformation to be applied.

8 Adapt the display file program such that the user can choose with a ScrollingList the font which is used to display the file.

9 Include in the program of exercise 5.7 a timer that scrolls to the next page automatically after a period of time which can be set by the user via an input dialog.

10 Extend an existing program using the function GetCurrentTime and a timer to display the time in hours and minutes every minute. Choose your own way to display the time: in words or as a nice picture using the draw functions from the I/O module deltaPicture.

11 (Large exercise) Extend the display file program with editing capabilities by extending the keyboard and mouse functions. Incorporate the results of exercises 5.6, 5.8 and 5.9 and extend it into your own window-based editor.

12 Change the line drawing program such that only horizontal and vertical lines can be drawn if the shift key is pressed during drawing. The line draw should be the 'best fit' of the line connecting the stating point and the current mouse position.

13 Extend the line drawing program such that the thickness of lines can be chosen from a sub-menu.

Chapter 6
1 In the function qsort there are two list comprehensions used to split the input list. It is possible to split the input list in one pass of the input list similar to msort4. Using an additional function it is possible to do this in one pass of the input list. Determine whether this increases the efficiency of the quick sort function.

2 To achieve the best of both worlds in the quick sort function you can combine splitting the input in one pass and continuation passing. Determine whether the combination of these optimizations does increase the efficiency.

3 When the elements of a list can have the same value it may be worthwhile to split the input list of the quick sort function in three parts: one part less than the first element, the second part equal to the first element and finally all elements greater than the first element. Implement this function and determine whether it increases the speed of sorting the random list. We can increase the amount of duplicates by appending the same list a number of times.

4 Determine and compare the runtime of the sorting functions msort4, qsort4 (from the previous exercise), tsort2 and isort for non-random lists. Use a sorted list and its reversed version as input of the sorting functions to determine execution times. Determine which sorting algorithm is the best.

5 Investigate whether it is useful to pass the length of the list to sort as additional argument to merge sort. This length needs to be computed only once by counting the elements. In recursive calls it can be computed in a single reduction step. We can give the function split a single argument as accumulator. Does this increase the efficiency?

6 Study the behavior of sorting functions for sorted lists and inversely sorted lists.

7 Determine the time complexity of the functions qsort2 and tsort2.