rackettyped-racket

Applying cast to dynamically required function in typed racket


I'm trying to load and use a function from a different module at run-time. The issue is that dynamic-require's range, Any, can't seem to be casted to a more specific (function) type.

test.rkt:

#lang typed/racket

(module other-module typed/racket
  (provide f)
  (: f : Integer -> Integer)
  (define (f x)
    (* x 2)))

; g has type Any because dynamic-require returns a value of type Any
(define g (dynamic-require '(submod "test.rkt" other-module) 'f))

;contract violation
;  Attempted to use a higher-order value passed as `Any` in untyped code: #<procedure:f>
;  in: Any
;  contract from: typed-world
;  blaming: cast
;   (assuming the contract is correct)
((cast g (-> Integer Integer)) 3)

Is there any way to load and use a function at run-time from a different module in #lang typed/racket?


Solution

  • One work-around is to do the loading in an untyped module and use require/typed to assign types:

    #lang typed/racket
    
    (module other-module typed/racket
      (provide f)
      (: f : Integer -> Integer)
      (define (f x)
        (* x 2)))
    
    (module another-module racket
      (define g (dynamic-require '(submod "test.rkt" other-module) 'f))
      (provide g))
    
    (require/typed 'another-module
      (g (-> Integer Integer)))
    
    (g 3)
    ;; 6
    

    But yeah, it would be nicer if dynamic-require could take a target type or Typed Racket allowed untyped regions (the opposite of with-type).