问题描述
我试图通过使用 require/typed
导入它来在类型化球拍中使用通用图形库,但我不断收到这些奇怪的长错误。有没有人设法让类型检查器与通用图形库合作?
#lang typed/racket
(require/typed graph
[#:opaque Graph graph?]
[unweighted-graph/undirected ((listof (List Any Any)) -> Graph)]
[add-edge! (Graph Any Any -> Void)])
(define g : Graph (unweighted-graph/undirected '((1 2) (1 3))))
(add-edge! g 2 3)
graph?: contract violation
any-wrap/c: Unable to protect opaque value passed as `Any`
value: #<unweighted-graph>
This warning will become an error in a future release.
in: the 1st argument of
a part of the or/c of
(or/c
struct-predicate-procedure?/c
(-> Any boolean?))
contract from: (interface for graph?)
解决方法
这并不理想,但有一个解决方法:
#lang typed/racket
(module wrapper racket
(provide graph? unweighted-graph/undirected add-edge!)
(require (prefix-in g: graph))
(struct graph [g]) ; struct generates the predicate
(define (unweighted-graph/undirected es) ; wrap output graph
(graph (g:unweighted-graph/undirected es)))
(define (add-edge! g a b) ; unwrap input graph
(g:add-edge! (graph-g g) a b)))
(require/typed 'wrapper
[#:opaque Graph graph?]
[unweighted-graph/undirected ((Listof (List Any Any)) -> Graph)]
[add-edge! (Graph Any Any -> Void)])
(define g : Graph (unweighted-graph/undirected '((1 2) (1 3))))
(add-edge! g 2 3)
当 Typed Racket require/typed
看到 #:opaque
时,它仍然需要将您提供的谓词 graph?
视为无类型代码。但它还需要使用来自无类型代码的谓词来保护有类型-无类型边界上的值。 graph?
谓词具有 (-> Any Boolean)
类型,因此当类型化球拍使用来自类型化代码的值调用它时,它会以类型 Any
传递它。但是,如果在此之前它有一个更具体的类型,涉及必须输入的输入,它仍然需要防止无类型代码以错误的方式“使用”,或提供错误的无类型输入。
通过创建一个不需要以相同方式“查看内部”值的新的 graph?
谓词,添加一个不透明的结构来回避这一点。