Student Homework and Presentation Record.

- Homework should be sent to me by email (RAbbott@
CalStateLA.edu ) to arrive by 9:00AM on the day it is due.- For each day, there should be
a single filesent as an attachment.- It should be possible to load that file into either HUGS or SWI-Prolog as appropriate.
- Answers that you get when you run the programs should be entered as comments.

**Functional Programming: **Hugs: Haskell/HUGS, Text: Haskell: The Craft of
Functional Programming (code: Downloads),
Wiki bulletin board for
new HUGS users.

**Prolog: **SWI Prolog

**March 29.**

**Homework due 4/5: **

- Download and install HUGS (Haskell/HUGS).
- Download and unzip the Haskell programs from the textbook web site (Downloads).
- Run the examples in the book from chapters 1 and 2.
- Exercises 2.1 - 2.5 (pp 29, 30).

**April 5.Types and Definitions: Thompson, Chapter 3.
**

Note that if you do not declare a type for a function, the type will be the most general that can be determined from the function definition. For example,

> sq :: Int ->
Int

> sq n = n * n

Will define sq as a function from Int to Int. If you try to execute: sq 5.4 you will get an error message. But if you define

> sq0 n = n * n

sq0 will be defined as a function from any Num(erical) type to itself. If you try to execute: sq0 5.4 you will get the correct answer. To check this, look up these functions using the Browse > Name menu selection.

Also note that to load Chapter3.hs or Chapter3.lhs you must modify the import statement:

> import Prelude hiding
(max)

> import Char hiding (toUpper, isDigit)

Apparently the Char library was extracted from the Prelude.

I can't get 4 'max' 5 to work. Can you? David Anthropoulos pointed out that it should be 4 `max` 5, using the backquote, the key to the left of the '1' key.

A reasonable way to think of what you are doing when associating values with identifiers (i.e., when writing an equation) is that you are both declaring the identifier and giving it a value. So:

> five = 5

declares the identifier "five" to be of type **Integer** and giving it a
value of 5. When you write

> square :: Int ->
Int

> square n = n * n

you are declaring square to be of the type **Int -> Int** and giving it
as a value the function that converts n into n * n.

In other words, in functional programming, what one would normally think of
as variables and what one would normally think of as functions are on the same
level. They are ** values** of some

**Homework due 4/12: **

- Exercises 3.3, 3.4, 3.5, 3.6, 3.7, 3.12 (note that toUpper is almost but not quite the answer; try toUpper 'A' to see why it is not the correct answer), 3.13.

**April 7.Introduction to Logic Programming and Prolog:
Clocksin, Chapter 1. **

To experiment with the last example in the chapter (p 11), create a file with the following content.

human(joe).

human(john).

honest(mary).

honest(john).

Load that file into Prolog; then run the goal:

?- trace, human(X), honest(X).

**Homework due 4/14: **

- Download and install SWI-Prolog. (SWI Prolog)
- Worksheets 1 - 4. To run a worksheet, create a file containing the predicates defined in the worksheet. Then run the goals indicated. For example, for Worksheet 1, create a file with the predicates male/2, female/2, and pair/2; start SWI-Prolog; run the goals at the bottom of the worksheet; and answer the questions.

**April 12.Recursion, tuples, and Lists: Thompson, Chapters
4 - 7 (selected parts). **

Also, note:

> switch:: (Int -> Int ->
Int) -> (Int -> Int -> Int)

> switch (-) =
(+)

> switch (+) = (-)

After the preceding definitions: (switch (-)) 3 4 yields 7.

However: (switch (+)) 3 4 also yields 7.

Apparently, it is not possible to compare two identifiers to determine
whether they refer to the same function.

**Homework due 4/19: **

- Exercises
- 4.9, 4.10, 4.13, 4.14 (Use recursive definition of isOdd and isEven; don't use `mod` or `rem`. You may use the definitions on pages 106 & 107 if you understand them and modify them to work for negative numbers as well as positive numbers.),
- 5.10 (Try only possible divisors between 2 and (sqrt n). Note sqrt requires a Float or Double argument. It may be tricky to get the numeric types to come out right.), 5.11,
- 7.6, 7.7, 7.8, 7.9, 7.11, 7.13.

**April 14.Recursion and Lists: Clockson, Chapters 2 and 3
(selected parts). **

**Homework due 4/21: **the
"Practice" exercises on the following pages: 19 (second "Practice"), 22, 24
(part 3 only), 32, 33 (don't do the "Practice" but fix setify/2 so that it works
correctly even on backtracking. It's a simple change to the 3^{rd}
clause. It requires that you use *not* or "\+" which Clockson hadn't
covered to that point in the book.), 35 (write the program alternate/3),
37.

Also write a single prolog predicate zipUnzip/3 that does the equivalent of zip and unzip in Haskell.

?- zipUnzip([1, 2, 3], [a, b, c], Z) .

Z = [(1, a), (2, b), (3, c)]

?- zipUnzip(A, B, [(1, a), (2, b), (3, c)]).

A = [1, 2, 3]

B = [a, b, c]

In other words, zipUnzip/3 works both "forwards" and "backwards."

**April 19.**

**Homework due 4/26: **

- 5.18 (It's trivial to get the answer. Be able to explain it also.)
- 9.2, 9.3, 9.6 - 9.10.

**April 21.**

**Homework due 4/28: **

- More list predicates. A number of list predicates are built into SWI-Prolog. See http://www.swi.psy.uva.nl/projects/SWI-Prolog/Manual/lists.html. Define your own versions of: delete/3, intersection/3, nth0/3, numlist/3, permutation/2, and select/3. Note that '+' preceding a parameter means that the parameter must be instantiated when the predicate is called; '-' means that the parameter must be uninstantiated when the predicate is called; '?' means that the parameter may be instantiated or not when the predicate is called. Note that on backtracking, permutation/2 should generate all permutations.
- Read Worksheet 22 (pp 47, 48) and define lookup/2 in the Practice p. 48.

**May 3.**

**Homework due 5/10: **

- 9.11, 9.12, 9.13,
- 9.14 (be able to explain why),
- 9.16 (just define filterFirst; don't worry about
returnLoan),

> filterFirst greaterThan4 [2, 6, 1, 7] --> [2, 1, 7] - 9.17
- 9.18 (redefine the functions in 9.7 using foldr or foldr1)

**May 5.**

**Homework due 5/12:
**Write predicates called eq/2 and notEq/2 that are equivalent to == and \==.

That is, eq(X, Y) should be identical to A == B, and notEq(X, Y) should be identical to X \== Y.

Note that A \== B is the same as \+ (A == B). So notEq(X, Y) should be
the same as \+ eq(X, Y). (It's ok to define notEq/2 in terms of eq/2 or *vice
versa,* whichever is easier.)

The call eq(A, B) should succeed if:

- A and B are both completely instantiated to the same value, i.e., they are both ground and have the same value;
- A and B are both variables that have been unified with each other;
- A and B are partially instantiated, i.e., they are terms that contain some ground sub-terms and some uninstantiated sub-terms, A and B can be unified (although eq/2 should not unify them), and the corresponding sub-terms all satisfy eq/2. For example, eq([A], [B]) should succeed or fail depending on whether eq(A, B) succeeds or fails. Similarly eq(f(A, B), f(C, D)) should succeed or fail depending on whether eq(A, C) and eq(B, D) succeeds or fails.

It should fail in all other cases. Of course, eq(A, B) should not change A or B. If they start as variables they should finish as variables. If they were not unified prior to the call eq(A, B), they should not be unified after the call.

For example, both

?- A = B, A == B.

and

?- A = C, B = D, f(A, B) == f(C, D).

succeed, whereas both

?- A == B.

and

?- f(A, B) == f(C, D).

fail.

In all cases, A, B, C, and D remain variables and do not become unified other than as indicated explicitly in the examples.

Note that different/2 in Clockson p. 50 is not the same as \==. If A and B have not been unified, different(A, B) fails, but A \== B succeeds. Clockson's different/2 means only that its arguments cannot unify, not that they are not eq/2.

Hints:

- The built-in predicate var/1 succeeds if its argument is an uninstantiated variable. It fails otherwise.
- The built-in predicate ground/1 succeeds if its argument is completely instantiated, i.e., contains no uninstantiated variables. It fails otherwise.
- \+ \+ P succeeds if and only if P succeeds. (After all, it is a double negation.) But if P has arguments that it instantiates, \+ \+ P does not instantiate those arguments. For example, if A starts out uninstantiated, \+ \+ (A = 3) succeeds without instantiating A to 3. If you use this trick, be able to explain why it works this way.
- To test whether two
*variables*have been unified (case (ii) of the definition of eq/2 above), try instantiating one and seeing whether the other becomes instantiated. More generally, to test whether two*terms*have been unified (case (iii) of the definition of eq/2 above), try grounding one and seeing whether the other becomes ground. - The predicate =.. (called Univ) takes any term and converts it into a list whose first element is the functor and whose remaining elements are the arguments. For example, f(a, b) =.. [f, a, b]. Univ works in both directions.
- The following predicate will ground its argument. Note the cuts, which
prevent a variable from being treated as a list or a term and prevent a list
from being treated as a general term. The cut in the first clause is not
needed and is there primarily as documentation.

% T is already ground. Do nothing

makeGround(T) :- ground(T), !.

% T is a variable. Make it the atom '$$$'. Not a good idea, but it will do for now.

makeGround(T) :- var(T), !, T = '$$$'.

% T is a list. Walk down the list and make each entry ground.

makeGround([T | Ts]) :- !, makeGround(T), makeGround(Ts).

% T is some other structure. Use Univ to convert T into a list. Once

% we have a list, we can ignore the functor, which is always ground,

% and walk down the list or arguments, making each of them ground.

makeGround(T) :- T =.. [_F | Args], makeGround(Args).

**May 10.Functions as values. Thompson **

**Homework due 5/17:
**Exercises 10.2, 10.3, 10.7, 10.8, 10.9. Exercise 10.10 is optional..

**May 12.Review homework. **

**Homework due 5/19: **.

Catch up..

This week this class will be taught using technologically mediated tools. Read the sections in advance. Then meet during the class period in the chat room on the CS_332 YahooGroups web site. Discuss the material amongst yourselves. Look over the homework during the discussion to be sure that you can handle it. Use the CS_332 mailing list as usual for problems you encounter after the chat room discussion.

**May 17.Partial application. Thompson **

**Homework due 5/24:
**Exercises 10.12, 10.13, 10.33, 10.34.

**May 19.findall/3. Look up findall/3 in the online
SWI-Prolog reference manual: **http://www.swi.psy.uva.nl/projects/SWI-Prolog/Manual/allsolutions.html.

**Homework due 5/26:
**.Write findall/3 versions of setify/2, union/3, intersection/3,
setDifference/3, and zip/3. Be sure that union/3 and intersection/3 return sets,
i.e., no duplicates.

**May 24.Overloading and type classes. Thompson
**

**Homework due 5/30:
**Exercises 12.1 - 12.3

**May 26.Difference Lists. Clockson Chapter
5. **

**Homework due 6/2: **.

Define the following predicates:

- Write the version of rotall/3 described at the bottom of page 57, i.e., using a counter as the second argument.
- toDiffList(+L, ?S-?E). Optionally make it work for toDiffList(?L, ?S-?E). You will need to use both var/1 and cut.
- appendWithDiffLists(?L1, ?L2, ?L3). The lists L1, L2, and L3 are not difference lists. appendWithDiffLists/3 should use toDiffList/2 to convert L1, L2, and L3 to equivalent difference lists. Then unify the appropriate variables (as the book describes) to do the appending. Finally, unify the "hole" at the end of the appended list with []. This should work both forwards and backwards without thinking too much about it.
- What are the computational complexities of the three possible append implementations.
- Append by repeatedly appending a singleton list made from the first element of the second argument to the end of the first argument.
- Append by using the standard prolog append/3.
- Append by using appendWithDiffLists/3.

**June 2.Lazy programming. Thompson **

**Homework due at final:
** exercises 17.24 and 17.25. See examples immediately below.

Main> take 10 (runningSum [0 .. ])

[0,1,3,6,10,15,21,28,36,45] :: [Integer]Main> take 10 (infiniteProduct [0 .. ] [ 0 .. ])

[(0,0),(1,0),(1,1),(2,0),(2,1),(2,2),(3,0),(3,1),(3,2),(3,3)] :: [(Integer,Integer)]

**Hint. **To write infiniteProduct, use the technique used in
pythagTriples (p. 365) but generate all possible pairs of *indices* into
the two argument lists. (If you have taken CS 486, this should be familiar as a
technique for generating certain infinite sets such as the set of all rational
numbers.) Recall that if xs is a list, xs!!j is the j^{th} element
of xs. It's not clear to me how to use infiniteProduct of just two lists to
generate the Pythagorean triples. It makes more sense to me to write
infiniteProduct to take three arguments rather than two. Then test each of the
triples to see if it is Pythagorean. If you do that, the indices themselves
could be the triples to be tested, so you are back to the original code for
pythagTriples. But write infiniteProduct with two (or three) argument
lists anyway. It should work no matter what the lists are.

*Please sign up for an appointment in lieu of a final exam. The sign
up sheet is at the course web site at: http://groups.yahoo.com/group/CS_332/files/.
Use the sheet with the latest version letter (a, b, c, ...). Select a convenient
time and fill in your name and email address. Then increment the version letter
(a -> b -> c -> d ...) and upload the revised sheet. If you find that
someone else has already uploaded a signup sheet with that version letter, the
two of you were modifying the sheet at the same time, and the other person beat
you. Start again with the new latest version.*