Ana Ramírez Chang
CS 302
Assignment 9 (groundwork and teams)

1. The following activities from assignment 4 would be appropriate for doing in a group.

  1. What is the difference between lazy evaluation and eager evaluation? Give an example when lazy evaluation would work better than eager evaluation.

    It would be useful to hear what examples other students come up with for when lazy or eager evaluation would work better.

  2. Given the expression:
      fun sqrt x = 
         let 
            fun good-enough guess = 
               Math.abs (guess * guess - x) < 0.001
            fun improve guess = 
               Math.average (guess, x/guess)
            fun sqrt-iter guess = 
               if good-enough guess then guess
               else sqrt-iter (improve guess)
         in
            sqrt-iter 1.0
         end
    	    
    Draw the environment diagram that results from evaluating the following expression: sqrt 1.

    Environment diagrams are very detail oriented, so working in a group would help students catch errors sooner without having to wait for the assignment to be graded and returned.

  3. Write a the function sum that takes a list of integers and returns the sum of all the integers using foldr.

    Working out the types for this exercise can be a little tricky and could benefit from someone to bounce ideas off of.

  4. Write a datatype for family tree.

    There is not only one correct datatype for a family tree, groups would help students brainstorm different datatypes. You could add to this exercise by asking the students to make sure the datatype satisfies certain properties. The group could then discuss the different datatypes to see which ones satisfy the specified properties.

  5. Write a function treefold, similar to foldr that takes a combination function and a tree.

    Once again, the types are tricky to figure out here, so it would help to try and explain the types to someone else to make sure they make sense to you.

2. Here are two activities that will faciliate group productivity:

  1. Understanding static vs. dynamic scoping
    In groups of two or three, each student should come up with an example expression that will evaluate to two different values if it is evaluated using static scoping or dynamic scoping. Then, the group members should swap examples and try and figure out what the two different values will be. This will ensure the students can come up with examles that work. If they don't work, the other students will not be able to come up with the two different values. This should result in a discussion about what is wrong with the example.
  2. Data abstraction
    In groups of four or five, divide the group into two groups of two to three. Each of the subgroups should desing a datatype and implement the functions layed out in the given signature. Each group should also write a set of tests to make sure their code works. The two subgroups shoud then swap their implementations and run thier tests on the other group's code. If the groups understand data absraction and the code is correct, the tests should pass on the other group's implementation. If not, the groups should go back and figure out what violation of the abstraction made the tests fail.

3. I think a group exam problem should be involved enough for each student to have the opportunity to give input. So a simple recall type problem whould not work well for a group exam. The foldr question on my midterm is significantly involved that it would work well for a group problem on the midterm, especially if each student took the test individually first, that way each student would have thought about the solution beforehand and could discuss their solutions as a group to come up with a revised solution. Here is the foldr problem from my midterm.

Question 3: Use the following representation for a binary tree for this question.

datatype 'a tree = Tree of 'a * 'a tree * 'a tree | Empty

For example, the value:

var tr: int tree = Tree(3,
                        Tree(2,
                             Tree(1, Empty, Empty),
                             Tree(7, Empty, Empty)),
                        Empty)           

represents the tree:

          3
         /
        2
       / \
      1   7  
  1. Implement tree_flatten: 'a tree -> 'a list. tree_flatten takes a tree and returns a flattened version as a list where the order of the elements in the list reflects a depth first traversal from left to right. For example: tree_flatten tr = [1, 2, 7, 3]
    fun tree_flatten Tree(elt, Empty, Empty) = [elt]
      | tree_flatten Tree(elt, Empty, rTree) = elt::(tree_flatten rTree)
      | tree_flatten Tree(elt, lTree, Empty) = tree_flatten lTree) @ elt
      | tree_flatten Tree(elt, lTree, rTree) =
             tree_flatten lTree) @ (elt::(tree_flatten rTree))

    Goal: Test understanding of simple recursion.

  2. Implement tree_flatten': 'a tree -> 'a list -> 'a list. tree_flatten' takes a tree and a list, flattens the treeas in tree_flattena nd returns the resulting list with the list it took in appeneded to the end. For example, tree_flatten' tr [15, 16, 17] = [1, 2, 7, 3, 15, 16, 17]

    You may not use "@" in your implementation.
    fun tree_flatten' Tree(elt, Empty, Empty) lst = elt::lst
      | tree_flatten' Tree(elt, Empty, rTree) lst = elt::(tree_flatten' rTree lst)
      | tree_flatten' Tree(elt, lTree, Empty) lst = tree_flatten' lTree elt
      | tree_flatten' Tree(elt, lTree, rTree) lst =
             tree_flatten' lTree elt::(tree_flatten' rTree lst)

    Goal: Test ability to build a list without using "@", and ability to implement similar functionality in two ways (parts a. and b.)

  3. treefold: ('a * 'b -> 'b) -> 'b -> 'a tree -> 'b. treefold folds a tree into a value of type 'b based on a combination function and a base balue of they 'b. (Similar to foldr)

    For example: The function tree_sum: int tree -> int that takes an integer tree and returns the sum of all the nodes can be implemented using treefold as follows.
    	  fun tree_sum tr = 
    	     let
    		    fun combfn(elt, sum) = elt + sum
    		 in
    		    treefold combfn 0 tr
    		end
    Implement treefold so that it traverses the tree depth first from left to right (similar to the traversal in tree_flatten and tree_flatten').
    fun treefold combfn base Tree(elt, Empty, Empty) = combfn(elt, base)

      | treefold combfn base Tree(elt, lTree, Empty =
             let
                var foldedLTree = treefold combfn base lTree (optional blank)
             in
                combfn (elt, foldedLTree)
             end

      | treefold combfn base Tree(elt, Empty, rTree) =
             let
                var combinedElt = combfn(elt, base)(optional blank)
             in
                treefold combfn combinedElt rTree
             end

      | treefold combfn base Tree(elt, lTree, rTree) =
              let
                var foldedLTree = treefold combfn base lTree (optional blank)
                var combinedElt = combfn(elt, foldedLTree)(optional blank)
             in
                treefold combfn combinedElt rTree
             end

    Goal: Test ability to transfer understanding of foldr to treefold.

  4. Re-implement tree_flatten:'a tree -> 'a list using treefold.
    fun tree_flatten tr =
       let
          fun combfn (elt, lst) = elt::lst
       in
          treefold combfn nil tr
       end

    Goal: Test ability to use treefold, including factoring out the combination function used in tree_flatten'.