The APC protocol has an unprecedentedly featureful type system.
Why? Types are very useful: They tell the computer how to parse the serialization format, how to represent the objects to users, how to structure documentation and help users to find it when they need it, how to generate bindings for different languages, how to assign globally unique IDs to different type components and interface handles of entities that will never clash, and how to notice, point out, and explain many classes of mistake that programmers might make which is important as soon as codebases get large.
Types are also just basic necessary part of what needs to be nailed down when humans want to agree on a shared data model.
So it makes sense for a meta-protocol to have a good distributed type system, a language for specifying types, a format for representing types to automated tooling.
Many upcoming meta-protocols have a decentralized process for maintaining datatype descriptions, usually called "schemas". ATProto has its "lexicons", Leaf has an entity component approach. Before them, Capnp did a great job with its schemas, though very few adopted capnp for some reason (I suspect due to confusion about its read-in-place APIs, which are less ergonomic than more conventional copy APIs. Capnp 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.)
Most of today's schema systems lack generics, type parameter bounds, interfaces, or dependent type parameters. Lacking interfaces is especially bad. Interfaces define how you can interact with a server or an actor. They make up most of the definitions of our APIs.
A strong type can project down to a weak type without problems. Dependent types translate down to member variables, const if possible. In langauges that lack generics, members of type <T:Bound>
project down to Bound
. Runtime type checks have to be done on each end anyway due to trustlessness.
Why not use capnp? Because capnp schemas are mutable, which introduces friction (user must generate a UUID to write a new schema) and syntactical noise (fields have to be tagged with numbers) and creates security issues (imagine a situation where a false schema serves an important certificate with some field names swapped around) and social coordination issues (what if the capnp repo has financial issues, and what if a schema's owner starts abusing their position or otherwise blocking protocol evolution).
Types don't really need to be able to change over time. 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 impl Deref<A> for AWithB
and impl Deref<B> for AWithB
which would make it basically behave equivalently to an intersection type. Rust's type system is strong!) 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.
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 offline, no matter how small their authors were, they'll be safe forever to build a standard upon.
You may want to see our schema language. I haven't defined one yet. I've been writing types raw in the underlying cross-language json format. It's important that the language be separable from the format. Languages need to be able to evolve over time. No language should reign forever. May the future of the AP protocol be long and surprising.