In discussions with some people at (seventh RacketCon), I managed to
solve a few open problems I had in my implementation of Hackett. One
thing I didn’t get a good answer for, however, is implementing a
language with multiple namespaces. Hackett is not dependently-typed, so
it is pointless and inconvenient for types and values to share the same
namespace; indeed, it is often useful and idiomatic in Haskell to reuse
names for both type variables and runtime variables.
Racket is, of course, a staunch Lisp-1, and it has a single namespace.
I generally think this is the right default, but for Hackett, I’ve
already run into situations in which I would strongly prefer the types
and value namespaces remain separate. Fortunately, Racket often makes
it possible to build these things as derived concepts, so I am hopeful
I will be able to implement this without too much pain.
I currently have an understanding of two possible approaches for
implementing multiple namespaces. The first appears to be the usual
technique of maintaining a separate binding table (using free id tables
from syntax/id-table). This is often good enough, but it isn’t good
enough for Hackett, since Hackett needs to support arbitrary local
bindings and bindings that can be tracked and renamed separately from
the Racket binding they are “attached” to. An alternative approach that
I have considered (and discussed briefly with some people) is to
introduce a “value” scope using make-syntax-introducer in
#%module-begin, then use a separate “type” scope when parsing types to
keep the two bindings completely separate. This seems more promising,
but it has problems of its own.
Specifically, the main question occurs when considering code that spans
more than a single module. What do require and provide do? For the
provide case, it doesn’t seem too hard to have a (type-out ....) provide
transformer, but what happens when a user requires the module? Since my
understanding is that modules essentially only provide a set of
*symbols* per phase, not identifiers, would I need to mangle names in
order to allow a module to export a type with the same name as a value?
Would I need to write my own version of require to handle this without
wrapping all imports in a require transformer? What about interop with
other Racket languages?
This seems like a significant burden to put on me as the author of a
language, but I don’t know of a better way. Is there prior art here? Is
there a simpler solution? And are there any pitfalls I haven’t yet
You received this message because you are subscribed to the Google Groups
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
For more options, visit https://groups.google.com/d/optout.