Homework 4: Higher-Order Functions

COMP 105, Fall 2019

Due Tue, Oct 8 @ 11:59pm

Higher-order functions are a cornerstone of functional programming. And they have migrated into all of the web/scripting languages, including JavaScript, Ruby, and Python. This assignment will help you incorporate first-class and higher-order functions into your programming practice.

This project uses the same μScheme interpreter as from Homework 3. There is no code skeleton for this project. By now, you should know where to put contracts, algebraic laws, and tests.

Answer these questions before starting the rest of the assignment.

  1. Review Sections 2.7.2, 2.8.1, and 2.8.2. Now consider each of the following functions: map filter exists? all? curry uncurry foldl foldr. Put each function into exactly one of the following four categories:

    (B) Always returns a Boolean
    (F) Always returns a function
    (L) Always returns a list
    (A) Can return anything (including a Boolean, a function, or a list)

  2. For the same functions as question 1, say which of the following five categories best describes it. Pick the most specific category (e.g., (S) is more specific than (L) or (M), and all of these are more specific than (?)).

    (S) Takes a list & a function; returns a list of exactly the same size
    (L) Takes a list & a function; returns a list of at least the same size
    (M) Takes a list & a function; returns a list of at most the same size
    (?) Might return a list
    (V) Never returns a list

  3. For the same functions as question 1, put each function into exactly one of the following categories. Always pick the most specific category (e.g. (F2) is more specific than (F)).

    (F) Takes a single argument: a function
    (F2) Takes a single argument: a function that itself takes two arguments
    (+) Takes more than one argument

  4. Review the difference between foldr and foldl in section 2.8.1. You may also find it helpful to look at their implementations in section 2.8.3, which starts on page 135; the implementations are at the end.

    1. Do you expect (foldl + 0 '(1 2 3)) and (foldr + 0 '(1 2 3)) to be the same or different?

    2. Do you expect (foldl cons '() '(1 2 3)) and (foldr cons '() '(1 2 3)) to be the same or different?

    3. Look at the initial basis, which is summarized on 161. Give one example of a function, other than + or cons, that can be passed as the first argument to foldl or foldr, such that foldl always returns exactly the same result as foldr.

    4. Give one example of a function, other than + or cons, that can be passed as the first argument to foldl or foldr, such that foldl may return a different result from foldr.

  5. Review function composition and currying, as described in section 2.7.2, which starts on page 130. Then judge the proposed properties below, which propose equality of functions, according to these rules:

    • Assume that names curry, o, <, *, cons, even?, and odd? have the definitions you would expect, but that m may have any value.

    • Each property proposes to equate two functions. If the functions are equal—which is to say, when both sides are applied to an argument, they always produce the same result—then mark the property Good. But if there is any argument on which the left-hand side produces different results from the right, mark the property Bad.

    Mark each property Good or Bad:

    ((curry <) m)     == (lambda (n) (< m n))
    
    ((curry <) m)     == (lambda (n) (< n m))
    
    ((curry cons) 10) == (lambda (xs) (cons 10 xs))
    
    (o odd?  (lambda (n) (* 3 n))) == odd?
    
    (o even? (lambda (n) (* 4 n))) == even?

In this part of the homework, you will use higher-order functions to develop an embedded domain-specific language (EDSL) for validating submitted web forms. For example here is a (fake!) web form:

Room scheduling request

course: Course-related
assoc: Student association meeting
other: Other

If this web form were real, then when you clicked on the Submit button, the data you filled in to the form would be sent to the web server. For this problem, we will assume that the web server is running µScheme, and that form values are translated into association lists (recall these are lists of key-value pairs), where the keys are the form fields and the values are those entered in the form. For example, for the above form, one such value might be:

(val sample-response
  '([purpose course]
    [building h]
    [room 209]
    [start-time 2000]
    [end-time 2030]
    [info (COMP 105 study group.)]))

The above value is sensible, but what if someone fills out the form incorrectly? For example, among other things, they might forget to select a purpose, they might enter a non-existent room number, or they might choose an end time that's before the start time. (Ignore the fact that the form doesn't specify a date!)

Thus, most web servers will validate form submissions before preceding further. Validation both checks that the submitted form fields are sensible and, if not, indicates the faults: which fields failed validation. The EDSL you develop will let you write validators like the following, which checks some of the key properties for our example:

(val reservation-checker
  (faults/switch 'building
    (bind #f (faults/always 'building)
       (bind 'h (faults/both
                    (faults/not-equal 'room 102)
                    (faults/not-equal 'room 209))
         (bind 'robn (faults/not-equal 'room 253) '())))))
Here, reservation-checker checks the following (in order from top to bottom). If building is empty (#f), validation always fails. If building is 'h, then validation fails if the 'room is neither 102 nor 209. If building is 'robn then validation fails if the 'room is not 253.

reservation-checker is itself a function that takes a response (like sample-response) and returns a list of faults, which are symbols that capture for the fields that failed validation. For example, if it returns '(building room) that indicates those two fields are bad, and if it returns '() that indicates the submitted form was valid.

Your job is to implement several functions that, together, form an EDSL for writing validators. Here are the functions you must write:

Expectations for these functions: