禁止对使用eval的球拍中的特定功能进行类型检查

时间:2019-12-29 11:04:40

标签: racket typed-racket

我需要绕过特定函数的类型检查器,但要使用该函数的类型签名来对程序的其他部分进行类型检查。我认为通常会使用cast,但是由于返回值的数量不固定,在这里失败了。

我正在将集合序列化为字符串,然后使用eval将其从字符串转换为集合。除了评估邪恶(我相信输入来源),如何在打字的球拍中处理这种情况? 这就是我的实现方式:

(: string->set (-> String (Setof Symbol)))
(define (string->set s)
  (eval (read (open-input-string s))))

这是类型检查器向我抛出的错误:

Type Checker: type mismatch;
;  mismatch in number of values
;   expected: 1 value
;   given: unknown number
;   in: (eval (read (open-input-string s)))
; [Due to errors, REPL is just module language, requires, and stub definitions]

我本质上需要具有类型检查器:

  1. 不要尝试对该方法进行类型检查,并且
  2. 信任给定字符串参数时返回一个集合的类型签名,然后继续对其余代码进行类型检查。

我该如何实现?

1 个答案:

答案 0 :(得分:2)

这里有两个问题。首先,eval返回多个值,而函数仅返回一个。其次,在返回的值eval中,每个值的类型均为Any,而您的函数则提供了更具体的信息。

第一个问题可以用call-with-values解决,它允许您将多个值转换为一个值(使用(lambda x x))。

第二个问题可以与cast一起使用。它会动态检查以确保类型适合,否则会动态地将值适合类型。

假设您知道eval语句只会返回一个值(或者您只关心返回的第一个值),则可以使用以下代码:

(: string->set (-> String (Setof Symbol)))
(define (string->set s)
  (define ret
    (first (call-with-values (λ () (eval (read (open-input-string s))))
                             (λ args args))))
  (cast ret (Setof Symbol)))

或者,您可以在Typed Racket中使用nocheck。我建议不要这样做。因为它禁用了整个模块中的所有类型检查。