Typed / Racket:给定自然数定义类型需要乘以两个数字来创建

时间:2016-07-10 17:40:00

标签: racket typed-racket church-encoding

鉴于以下定义的结构和类型需要编写乘法两个数字函数。无法做到这一点。任何建议将不胜感激。

(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))]))

1 个答案:

答案 0 :(得分:1)

您的sub-nat实施不正确,不会进行类型检查。虽然您可以解决这个问题,但从语义上讲,在Succ-n中使用multiply-nat更为正确(正如您对add-nat所做的那样),因为Succ-n是教会数字相当于sub1。这是multiply-nat的更正(和测试)版本:

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

出于测试目的,我还写了一个nat->number函数,用于将教会数字转换为实际数字:

(: nat->number : Nat -> Nonnegative-Integer)
(define (nat->number n)
  (if (Zero? n)
      0
      (add1 (nat->number (Succ-n n)))))