Peeyush Kushwaha
Peeyush Kushwaha

Reputation: 3623

Supressing type-checking for a particular function in racket that uses eval

I need to bypass the typechecker for a particular function but have the function's type signature available for type-checking other parts of the program. I think generally cast would be used, but that fails here because of variable number of return values.

I'm serializing a set to a string, and then using eval to convert it from a string to set again. Eval evilness aside (I trust source of input), how do I handle this in typed racket? This is what my implementation is:

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

And this is the error that type checker throws at me:

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]

I essentially need to have the typechecker to:

  1. Not try to typecheck this method, and
  2. Trust the type signature that it returns a set when it's given a string argument, and continue typechecking rest of the code.

How can I make that happen?

Upvotes: 1

Views: 111

Answers (1)

Leif Andersen
Leif Andersen

Reputation: 22332

There are two problems here. First, eval, returns multiple values while your function returns only one. Second, of the values eval returns, it has Any type for each value, while your function promises something more specific.

The first problem can be solved with call-with-values, which allows you to convert multiple values into just a single value (using (lambda x x)).

The second problem can be used with cast. It does dynamically check to make sure the type fits, but otherwise lets you dynamically fit a value into a type.

Provided that you know the eval statement will only return one value (or you only care about the first value returned), you can use the following code:

(: 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)))

Alternatively you could use use nocheck in Typed Racket. I would recommend against doing that though. As it disables all type checking in the entire module.

Upvotes: 4

Related Questions