首页 > 解决方案 > 禁止对使用 eval 的球拍中的特定功能进行类型检查

问题描述

我需要绕过特定函数的类型检查器,但让函数的类型签名可用于对程序的其他部分进行类型检查。我认为通常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. 相信当给定一个字符串参数时它返回一个集合的类型签名,并继续对其余代码进行类型检查。

我怎样才能做到这一点?

标签: rackettyped-racket

解决方案


这里有两个问题。首先,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)))

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


推荐阅读