Modular Types

By mako (@mako.dreamshrine.org)
Published:

edit: whitewind has repeatedly lost sections of this post while I was editing it. I'm done with whitewind (other problems include interfering with common browser shortcuts like ctrl+l (badly), ctrl+tab, being slow, various small things. I'll probably be on hackmd).

This was mostly just a draft/prospective thing though.

? specifically, or perhaps it's just a member value, ie, class Signature { date: DateTime, author: Profile, signing: Hash, signature: RSASig }, and perhaps this implicitly defines a number of type parameters, Signature<date: DateTime = Dynamic, author: Profile = Dynamic...>. which default to a Dynamic variant which means they can't be checked in type expressions or allocation.)

<!-- this wasn't a good point. Interfaces are trivial to add to any structure schema standard, and there isn't a need for generating interfaces/bindings straight from schemas in the pre-agoric regime: right now servers are much harder to 'make' than clients, so it doesn't matter if they all have to write their own bindings, which are all very bespoke anyway - Lacking interfaces is especially bad. Interfaces define member functions, ie, how you can interact with a remote actor, ie, a server. The interface is the first and sometimes last thing a user needs to know about an API. -->

Before them, Capnp did a great job with its schemas, though very few adopted capnp, for I think mostly dumb reasons (I suspect people saw its read-in-place APIs, which are less ergonomic than more conventional copy APIs, and decided the whole thing was a step down. But having in-place APIs didn't at all preclude the writing of a copy API, but I guess nobody who was a fan of capnp anticipated that the increased parsing speed granted by the slightly more complex in-place APIs wouldn't be enough to make them popular.)

But a problem shared by Capnp and ATProto is the mutation of types over time. This forbids us from using content-addresses for types (capnp addresses types with uuids, atproto with urls using dn). Using the content-address as the ID essentially means that anyone can re-host a type, and anyone who they serve it to will know that it really is the original type that was defined against that ID, which means that these type definitions will never go missing as long as someone's using them. It means that it doesn't matter who authored them, they'll be safe forever to build on.

But content-addressed data can't be altered. If you want to change a type, you can define a new one and define translators for the old one. If you want to add a few fields without replacing the type, you can add another component to the entity that has those fields (intersection types) (In languages that lack intersection types, A & B projects down to AWithB { a: A, b: B }. In rust, could also have impl Deref<A> for AWithB and impl Deref<B> for AWithB which would make it basically behave equivalently to an intersection type.) If you use a custom glossary, you can assign ids to these type components that are about as concise as capnp's field numbers. If you don't use your own glossary, each component will be id'd with the content-address of its type.

You may want to see the schema language. I haven't defined one yet. I've been writing types raw in the underlying cross-language cbor format. It's important that the schema language that most people write in is distinct from the schema format. Languages need to be able to evolve over time and no language should reign forever, while the format needs to be stable.

Help or fight?

I've been talking like these shortcomings are condemnatory of the other formats, but really maybe really we should just take those formats and improve them a little. But I don't want to, I'd love to just start from scratch, I don't think there are real benefits to interoperating with these systems given that they're all just microblogging communities (some of the most toxic commenters you can get), and their third-party login UX sucks (mastodon requires you to type your username in and afaik is multistage, bsky keeps logging me out), so like, what's the point???

But I believe we should try to colaborate anyway, for spiritual reasons.

So I'm going to talk about how pre-existing systems could be made more flexible.

Features: