Rewritten to use Typed Racket and expanded to be more complete