0

Given the following defined structures and type need to write multiply two numbers function. Having trouble to do that. Any advice will be greatly appreciated.

(define-struct Zero ())

(define-struct Succ
  ([n : Nat]))

(define-type Nat (U Zero Succ))

(: one Nat)
(define one (Succ (Zero)))
(: two Nat)
(define two (Succ one))

( : sub-nat : Nat Nat -> Nat)
   (define (sub-nat a y)
     (cond
       [(Zero? a) a]
       [(eq? one y)
          (- a y)]))

( : add-nat ( -> Nat Nat Nat))
(define (add-nat a b)
  (cond
    [(Zero? a) b]
    ((Zero? b) a)
    [else (add-nat (Succ-n a) (Succ b))]))

( : multiply-nat : Number Nat -> Nat)
(define (multiply-nat a b)
 (cond
   [(Zero? a) a]
   [(Zero? b) b]
    [else
     (add-nat b (multiply-nat (sub-nat a one) b))]))
C. K. Young
  • 219,335
  • 46
  • 382
  • 435
Lyudmila
  • 1
  • 1

1 Answers1

1

Your sub-nat implementation is incorrect and will not type-check. While you can fix that, semantically it's more correct to just use Succ-n in your multiply-nat (just as you do for add-nat), since Succ-n is the Church numeral equivalent of sub1. Here's a corrected (and tested) version of multiply-nat:

(define (multiply-nat a b)
 (cond
   [(Zero? a) a]
   [(Zero? b) b]
   [else
    (add-nat b (multiply-nat (Succ-n a) b))]))

For testing purposes, I also wrote a nat->number function for converting the Church numerals to actual numerals:

(: nat->number : Nat -> Nonnegative-Integer)
(define (nat->number n)
  (if (Zero? n)
      0
      (add1 (nat->number (Succ-n n)))))
C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • 1
    The issue isn't with the base cases, since they still will be zero in those branchs. It looks like the problem is closer to being in the use of `sub-nat`, since that's the only thing that's actually different between your version (using `(Succ-n a)`) and the original (using `(sub-nat a one)`). – Alex Knauth Jul 10 '16 at 21:39
  • @AlexKnauth Having reread the OP's case, I see their base cases would have worked too. Yes, their implementation of `sub-nat` is busted and won't type-check, and since `add-nat` already uses `Succ-n`, `multiply-nat` should use it too. – C. K. Young Jul 10 '16 at 21:42
  • Should you edit this to specify that it's `sub-nat` that's wrong, and leave the base cases alone? – Alex Knauth Jul 10 '16 at 21:53
  • 1
    @Lyudmila Glad to be of help. You can click on the big tick next to the up/down vote arrows to tell the site the problem is solved. – C. K. Young Jul 12 '16 at 21:14