Test 2 Solutions: Questions

X2.1.

[8 pts] What is the most general possible type for the following Haskell function? Describe the type using Haskell syntax.

threshold f z x = if f x < z then f x else z
X2.2.

[12 pts] Consider the Python program below.

def a():
    nonlocal x
    x = 9

def b():
    x = 8       # creates a new 'x' variable hiding the global 'x'
    a()
    print(x)

x = 7           # creates a global 'x' variable
b()
print(x)

a. If Python used dynamically scoped variables, what would this program display?

b. Why do all modern languages use lexical scoping (static scoping) rather than dynamic scoping?

X2.3.

[8 pts] Explain why the variable arr in the below Python program cannot be stored on the stack.

def sequenceComputer(ab):
    arr = [ab]
    def sequenceComp(n):
        while len(arr) <= n:
            arr.append(arr[-2] + arr[-1])
        return arr[n]
    return sequenceComp

fib = sequenceComputer(01)
print(fib(20))
X2.4.

[8 pts] Both C++ and Java allow a programmer to use a class name as a parameter to a generic class. Neglecting syntax and other usage rules, distinguish how the language have a different underlying implementation of such generics.

X2.5.

[8 pts] Convert the following Haskell function into an equivalent tail-recursive function.

hailstone n | n == 1 = 1
            | odd n  = 1 + hailstone (3 * n + 1)
            | even n = 1 + hailstone (n `div2)
X2.6.

[10 pts] Prove the following using our axiomatic scheme, including the Rules of Preconditions, Assignment, and Sequence.

x ≥ 1 }
y = x * x;
y ≥ 1 }
X2.7.

[6 pts] What loop invariant allows you to prove the postcondition for the following?

n ≥ 1 }
k = a[n];
i = n - 1;
while (i >= 1) {
    k = k + a[i];
    i = i - 1;
}

k = ∑j = 1n aj }
X2.8.

[6 pts] Convert the following Haskell expression using do notation to the equivalent non-do form using the Monad operators >> and >>=.

do putStr "Name: "
   name <- getLine
   putStrLn ("Hello " ++ name)
X2.9.

[8 pts] Distinguish the >> and >>= operators for monads in Haskell.

X2.10.

[8 pts] Write a function main with type IO () which reads two lines from the user and displays them in sorted order. You should not use any functions except for getLine, putStrLn, string comparison operators, and the monad sequencing operators (perhaps used implicitly through do notation).

X2.11.

[8 pts] Based on the BNF grammar below, draw a syntax tree for the sentence x x y x y x.

S T y T
T x | x S
X2.12.

[10 pts] Using BNF syntax, write a context-free grammar for the language of binary numbers: i.e., every sentence begins with a 1 followed by any sequence of 0's and 1's, except that 0 alone is also a sentence. Examples include 0, 1, 100, and 1111, but not 00 or 0101.

Test 2 Solutions: Solutions

X2.1.
Ord a => (b -> a-> a -> b -> a
X2.2.

a. 9 then 7

b. Dynamic scoping easily leads to unexpected program behavior. Taking the above program as an example, a programmer writing a may well be unaware of which functions use a, but still need to reference a variable in an outer scope. And in writing b, a programmer could accidentally define a variable with that same name.

X2.3.

While the variable arr is a variable local to the sequenceComputer function, its value persists beyond the end of the function call since the returned function sequenceComp (later named to fib) will need its value when it's called. Since its value must be kept beyond the end of the function call where it is created, space for the variable must be allocated on the heap.

X2.4.

In C++, a generic (“template”) is used to generate a new class definition for each usage of it with a different type, and each of these definitions is compiled separately. In Java, there is only one instance of the generic compiled, and it is compiled to deal with Object as the generic parameter. The type information with the generic is used only for type-checking by the compiler.

X2.5.
hailstone n = sub n 1
  where sub n k | n == 1 = k
                | odd n  = sub (3 * n + 1) (k + 1)
                | even n = sub (n `div2) (k + 1)
X2.6.
1. x ≥ 1 ⇒ x ⋅ x ≥ 1 Mathematical fact
2.x ⋅ x ≥ 1 }
y = x * x;
y ≥ 1 }
Assignment
3.x ≥ 1 }
y = x * x;
y ≥ 1 }
Preconditions: 1, 2
X2.7.
k = ∑j = i + 1n aj }
X2.8.
putStr "Name: " >> (getLine >>= (\name -> putStrLn ("Hello " ++ name)))
X2.9.

The >> operator expects a monad on both sides; it sequences the first monad with the second, with the overall result being the second monad's result (and the first monad's result discarded). While >>= also expects a monad on the left side, the right side should be a function that takes the result from the left-side monad to produce a second monad; the overall result is the second monad's result.

X2.10.
main =
 do a <- getLine
    b <- getLine
    if a < b then
        do  putStrLn a
            putStrLn b
     else
        do  putStrLn b
            putStrLn a
X2.11.
X2.12.
S 0 | 1 T
T 0 T | 1 T