Typed Racket 中的 Racket 通用图形库

Racket Generic Graph Library in Typed Racket

我试图通过使用 require/typed 导入它来在 typed racket 中使用通用图形库,但我不断收到这些奇怪的长错误。有没有人设法让类型检查器与通用图形库合作?

#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),因此当 typed racket 使用类型代码中的值调用它时,它会使用类型 Any 传递它。但是,如果在此之前它有一个更具体的类型,涉及必须输入的输入,它仍然需要防止非类型代码以错误的方式“使用它”,或者提供错误的非类型输入。

添加一个不透明的结构通过创建一个新的 graph? 谓词来回避这个问题,该谓词不需要以相同的方式“查看”值。