[racket] htdp: exercise 21.1.3

From: Daniel Bastos (dbastos at toledo.com)
Date: Thu Sep 25 12:48:05 EDT 2014

The solution is missing, but I thought of exposing this one here so that it
gets scrutinized before sending it to Robby Findler.

;; Exercise 21.1.3. Define natural-f, which is the abstraction of the
;; following two functions:
;;
;; ;; copy : N X  ->  (listof X)
;; ;; to create a list that contains
;; ;; obj n times
;; (define (copy n obj)
;;   (cond
;;     [(zero? n) empty]
;;     [else (cons obj
;;                 (copy (sub1 n) obj))]))
;;
;; ;; n-adder : N number  ->  number
;; ;; to add n to x using
;; ;; (+ 1 ...) only
;; (define (n-adder n x)
;;   (cond
;;     [(zero? n) x]
;;     [else (+ 1
;;              (n-adder (sub1 n) x))]))
;;
;; Don't forget to test natural-f. Also use natural-f to define
;; n-multiplier, which consumes n and x and produces n times x with
;; additions only. Use the examples to formulate a contract.
;;
;; Hint: The two function differ more than, say, the functions sum and
;; product in exercise 21.1.2. In particular, the base case in one
;; instance is a argument of the function, where in the other it is just
;; a constant value.
;;
;; (*) Solution
;;
;; After following the design recipe for abstraction, we get natural-f as
;; shown below. To write the contract, let's first only consider copy,
;; then we consider only n-adder and then we consider both.
;;
;; ;; natural-f-copy: Nat X (X (listof X) -> (listof X)) (listof X) ->
(listof X)
;; ;; natural-f-adder: Nat number (number number -> number) number -> number
;;
;; The contract for natural-f-adder is more specific than
;; natural-f-copy. The difference between these is that in the first, two
;; different types are involved --- X and (listof X). Therefore, (listof
;; X) works as another variable, so let's call it Y in the final version.

;; natural-f: Nat X (X Y -> Y) Y -> Y
(define (natural-f n x f init)
  (cond
    [(zero? n) init]
    [else (f x
              (natural-f (sub1 n) x f init))]))

;; (*) Tests

;; Let's use two different types in copy, say symbol and then number.

(check-expect (copy 3 'a) '(a a a))
(check-expect (natural-f 3 'a cons empty) (copy 3 'a))

(check-expect (copy 0 'a) empty)
(check-expect (natural-f 0 'a cons empty) (copy 0 'a))

(check-expect (copy 3 1) (list 1 1 1))
(check-expect (natural-f 3 1 cons empty) (copy 3 1))

;; For n-adder, let's make sure to test different init-values.

(check-expect (n-adder 3 3.14) 6.14)
(check-expect (natural-f 3 1 + 3.14) (n-adder 3 3.14))

(check-expect (n-adder 3 1) 4)
(check-expect (natural-f 3 1 + 1) (n-adder 3 1))

(check-expect (n-adder 3 2) 5)
(check-expect (natural-f 3 1 + 2) (n-adder 3 2))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140925/ea097a92/attachment.html>

Posted on the users mailing list.