Pre-release: Shallow and Optional Types

Typed Racket comes with two faster-but-weaker alternatives to its normal "Deep" types in the latest snapshot builds:

Give them a try & report any issues!

"Faster but weaker" refers to the way these languages enforce types at the boundaries to untyped code:

  • Deep TR (#lang typed/racket) enforces types with contracts, which may add a huge run-time cost but always protect against miscommunications.
  • Shallow TR (#lang typed/racket/shallow) enforces types with shape checks, which run quickly but detect only big mistakes --- e.g., expected a list, got a string. Very useful for typed scripts that interact with untyped libraries.
  • Optional TR (#lang typed/racket/optional) enforces types with ... nothing! Types are checked statically and are not enforced at run-time.

All three use the same static typechecker.

Further reading:


Very cool! I'm guessing that neither of these two new modes affect compilation times much?

Nope, not much. Type checking is as fast or slow as ever.

There is some change after typechecking because there are 3 paths now (generate contracts vs shape checks etc), but I haven’t noticed big differences.


Does this mean that libs heavily using typed/racket, such as math/array might become usable from plain racket by just changing the #lang line at the top of every lib file? @soegaard, could we finally be removing the 50x performance penalty warning soon?


Optional types cannot detect incorrect type assumptions and therefore do not enable type-driven optimizations

Would it be possible to apply optimizations by assuming the type signatures are correct?

One use is for timing: By converting one "hot spot" module and adding only annotations for anything else, you would get full TR optimizations and no contract slowdown. So you could measure the "best-case" scenario when deciding whether to convert a whole project to TR.

The downside: Optimized Optional TR could cause a segfault by e.g. an unsafe-vector-ref being applied to a list that somebody claims is a vector. At least it's now easy to change to shallow/deep for debugging. But that might not be enough in a security context(Racket websites exposed to the general internet, or a Discord bot that evaluates arbitrary code), so maybe hide it behind an option?

1 Like

I hope so! Let's talk more at racket/math #75

For extreme speed, I'd go with unsafe-provide and unsafe-require/typed
(in #lang typed/racket)

1 Like

That would be great - let's hear what Ben thinks.

1 Like