[racket] making libraries work natively with both Racket & Typed Racket
Is there an approved way of using #lang typed/racket/base/no-check (or maybe `with-type`) to create libraries that have both a typed and untyped interface? (The goal being to avoid use of `require/typed`)
For instance, the following works, but maybe it's a bad idea for other reasons:
;;;;;;;;;;;;;;;;;;;
;; adder.rkt = write typed code, but leave off #lang line & `provide`
(: fladd (Flonum Flonum . -> . Flonum))
(define (fladd f1 f2)
(+ f1 f2))
;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;
;; typed.rkt = compile in typed context
#lang typed/racket/base
(require racket/include)
(provide fladd)
(include "adder.rkt")
;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;
;; untyped.rkt = compile in untyped context with contract
#lang typed/racket/base/no-check
(require racket/include racket/contract racket/math)
(provide (contract-out [fladd (flonum? flonum? . -> . flonum?)]))
(include "adder.rkt")
;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;
;; test.rkt
#lang racket/base
(module typed typed/racket/base
(require "typed.rkt")
(require typed/rackunit)
(check-equal? (fladd 1.0 2.0) 3.0)) ; typechecks correctly
(module untyped racket/base
(require "untyped.rkt")
(require rackunit)
(check-equal? (fladd 1.0 2.0) 3.0) ; meets `provide` contract
(check-exn exn:fail:contract? (λ () (fladd 1 2)))) ; violates `provide` contract
(module violator racket/base
(require "typed.rkt")
(require rackunit)
(check-exn exn:fail:contract? (λ () (fladd 1 2)))) ; violates typed/untyped contract barrier
(require 'typed)
(require 'untyped)
(require 'violator)
;;;;;;;;;;;;;;;;;;;