我需要绕过特定函数的类型检查器,但要使用该函数的类型签名来对程序的其他部分进行类型检查。我认为通常会使用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]
我本质上需要具有类型检查器:
我该如何实现?
答案 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
。我建议不要这样做。因为它禁用了整个模块中的所有类型检查。