有没有办法在(类型)结构旁边定义Typed Racket中整个结构的合约?在我的特定情况下,我有一个结构,它将两个列表作为字段,我想要求列表具有相同的长度。
我看过:
make-struct-type
,它允许指定一个缓和构造函数调用的“guard”。如果长度不匹配,我可以传递引发异常的过程,但我不知道如何处理make-struct-type
返回的值。struct/c
和struct
形式的contract-out
,两者都根据各个字段的合同生成结构合同。这似乎无济于事。理想情况下,我想立即将合同绑定到结构(如define/contract
),但我可以在provide
类型的过程中添加合同。但是,我目前单独提供识别器和访问器程序,而不是使用struct-out
(以便我可以排除或重命名单个程序),并且我希望保持这种灵活性。
现在我有这样的事情:
(provide
(rename-out
[MyStruct my-struct]
[MyStruct? my-struct?]
[MyStruct-foo my-struct-foo]
[MyStruct-bar my-struct-bar]
)
)
(struct MyStruct (
[foo : (Listof Symbol)]
[bar : (Listof Any)]
))
答案 0 :(得分:2)
哇。我很惊讶在Typed Racket中做到这一点有多么困难。在普通(无类型)Racket中,它就像在struct
中添加#:guard
一样简单。不幸的是,Typed Racket中的struct
表单并不支持它。
因此,为了解决这个问题,我将生成一个带有私有(到模块)构造函数名称的结构类型,然后创建自己的构造函数,实际执行您希望它检查的契约。
这最终会看起来像:
(struct env ([keys : (Listof Symbol)]
[values : (Listof Any)])
#:constructor-name internal-env)
(: make-env (-> (Listof Symbol) (Listof Any) env))
(define (make-env k v)
(unless (= (length k) (length v))
(raise-arguments-error 'env
"env key and value counts don't match"
"keys" k
"values" v))
(internal-env k v))
现在,当您提供结构时,只是不提供internal-env
,但确实提供make-env
功能:
(provide (except-out (struct-out env)
internal-env)
make-env)
现在,当我构造一个env时,我得到(动态)检查以确保列表长度匹配:
> (make-env '() '())
#<env>
> (make-env '(a) '(1))
#<env>
> (make-env '(a) '())
env: env key and value counts don't match
keys: '(a)
values: '()
答案 1 :(得分:0)
您可能会发现从Racket定义并提供带有保护功能的结构定义,然后在Typed Racket中对结构进行需求/类型化和类型注释,这比单纯在Typed Racket中实现相同效果要简单得多。