我正在尝试在以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
属性。
我知道我可以不用合同就手动进行检查-但这似乎恰好是签订合同的情况。
谢谢!
答案 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
|#