用合同实现算术模N

时间:2019-04-28 00:15:41

标签: racket

我正在尝试在以N为模的字段中实现算术。这是一个简化的示例:

(struct field-element (number prime) #:transparent)

(define (field-element-add fe1 fe2)
  (field-element (modulo (+ (field-element-number fe1)
                            (field-element-number fe2))
                         (field-element-prime fe1))
                 (field-element-prime fe1)))

(field-element-add (field-element 3 5) (field-element 4 5))    ; (1)
(field-element-add (field-element 3 5) (field-element 4 6))    ; (2)

(1)应该返回(field-element 2 5),因为3 + 4 = 7 = 2 mod 5

(2)应该引发错误,因为您不能在具有不同素数模数的字段中添加元素(在此示例中为5和6)。

我的问题:如何使用检查field-element-add的所有参数的合同共享同一prime并在不这样做的情况下引发错误?

我在docs中看到的所有合同分别对每个参数施加约束,例如integer?。但是我想对一组参数强制执行约束:它们必须共享一个prime属性。

我知道我可以不用合同就手动进行检查-但这似乎恰好是签订合同的情况。

谢谢!

1 个答案:

答案 0 :(得分:2)

在您提到的页面中,请查看7.3.6部分中有关如何使用->i的信息,以便您可以“提及”其他参数。

针对您的情况:

(struct field-element (number prime) #:transparent)

(define field-binop/c
  (->i ([a field-element?]
        [b (a) (struct/c field-element
                         number?
                         (=/c (field-element-prime a)))])
       [result field-element?]))

(define/contract (field-element-add fe1 fe2) field-binop/c
  (field-element (modulo (+ (field-element-number fe1)
                            (field-element-number fe2))
                         (field-element-prime fe1))
                 (field-element-prime fe1)))

(field-element-add (field-element 3 5) (field-element 4 5)) ;=> (field-element 2 5)
(field-element-add (field-element 3 5) (field-element 4 6))

#|
../../Applications/Racket v7.2/collects/racket/contract/private/blame.rkt:347:0: field-element-add: contract violation
  expected: (struct/c field-element number? (=/c 5))
  given: (field-element 4 6)
  in: the fe2 argument of
      (->i
       ((fe1 field-element?)
        (fe2
         (fe1)
         (struct/c
          field-element
          number?
          (=/c (field-element-prime fe1)))))
       (result field-element?))
  contract from: (function field-element-add)
  blaming: anonymous-module
   (assuming the contract is correct)
  at: unsaved-editor:5.18
|#