To derive strict programmatic shapes uses an algebraic vocabulary over types represents 0 Zero an uninhabited type represents 1 Unit a type with exactly one state represents A B Alternatives a coproduct where exactly one alternative is present represents A B Products a type where all fields are present simultaneously These states can also be used to express the standard vocabulary types 1 T It is either empty unit or contains similar to T E It contains either success or error similar to The symbol indicates an equivalent state shape an information level correspondence not is its own distinct C type but algebraically it behaves as Zero is not unit In s algebra zero and unit are strictly separated is uninhabited you cannot construct it Algebraically it is is the one nullary product value You can construct it via or Algebraically it is Because exists applying a callable to it invokes a nullary function Because is uninhabited providing a callback over is statically proven to be unreachable code dead code In C is often conflated with empty state but algebraically is a unit type similar to Consider the difference in these carrier states Computation Meaning code expected<T copack<>> type InlinedCode text An expected value that type SimpleText type StrongEmphasis content text cannot fail type SimpleText text because its error state is uninhabited type SimpleText code expected<copack<> E> type InlinedCode text An expected value that type SimpleText type StrongEmphasis content text cannot succeed type SimpleText text because its success state is uninhabited type SimpleText code optional<copack<>> type InlinedCode text An optional that type SimpleText type StrongEmphasis content text must be empty type SimpleText text as its value state is uninhabited type SimpleText code expected<void E> type InlinedCode text An expected that yields type SimpleText type StrongEmphasis content text no value on success type SimpleText text but can fail with type SimpleText code E type InlinedCode text type SimpleText Copacks use set semantics A major feature of is that forms canonical sets of types in contrast to the positional indexing of When you combine types into a coproduct guarantees deduplication flattening and a canonical ordering NOTE Note copack vs copack_for In C there is no native language feature to represent a set of types Template parameter lists are always positional variadic sequences Syntactically this means and would be completely distinct typesa property that directly violates the mathematical commutative law of set union To enforce set semantics at compile time defines one canonical representation and rejects any instantiation that diverges from it is the core storage type It requires its template parameters to already be flat unique and sorted in a strict total order over types The order is derived from the compiler s own spelling of each type a build targeting C 26 with set will use to derive the order of types while the default build uses a type sorting mechanism based on compiler specific type names since these two orders may differ each defines a distinct ABI namespace If you attempt to instantiate manually with out of order parameters such as when precedes in that order or with nested copacks such as the compiler will reject the instantiation as outright ill formed is the user facing type alias It accepts any list of types out of order duplicates nested copacks performs the flattening deduplication and canonical sorting and resolves to the validated In an API signature the two are the same type since the alias resolves to in prose and code names the normalized state shape and the construction utility and stand in the same relation over the alternatives of the underlying Best practice spell rather than so that no spelling in your project is tied to one compiler s ordering The laws governing are Commutative Order of types does not change the resulting set Associative Nesting copacks is equivalent to flattening them Idempotent Duplicate types are collapsed into one Identity acts as the union unit adding changes nothing Idempotence means a set cannot carry positional meaning is one alternative not two Types combined into a should therefore be strongly typed tag structs or distinct domain objects never generic primitives whose meaning depends on where they sit Two distinct types that the ordering mechanism cannot distinguish are a different matter the library rejects them outright via a compile time assertion rather than silently merging them guaranteeing that no type is ever silently lost The algebra is strictly opt in The library relies on explicit consent It does not silently reinterpret arbitrary C types as products or coproducts remains a standard tuple does not acquire set semantics Tuple like participation in changes call shape applicability but it does not change the stored type identity A plain does not automatically become graded To invoke the algebra you use the opt in mechanisms provided by the library Direct construction of and Explicit conversions via and Member helpers for explicit type lifting detailed in Graded expected exact error sets If a side is already a or forwarding it behaves naturally without nesting A on the error side of enables error set unioning Because monadic operations introduce no grade themselves widens a graded error side but rejects a differing ungraded one Graded expected exact error sets gives the exact promotion rules libfn copack<> pack<> copack<A B> pack<A B> std optional<T> T copack_for<T std nullopt_t> std expected<T E> T E copack_for<T fn unexpected<E>> std same_as std optional<T> 1 T libfn copack<> 0 pack<> pack<> fn as_pack 1 pack<> copack<> copack<> void void 1 pack<> libfn copack std variant fn copack_for auto test_copack_set_semantics > void using SetA fn copack_for<NotANumber OutOfRange> using SetB fn copack_for<Missing OutOfRange> Flattening deduplication and reordering happen automatically using Union fn copack_for<SetA SetB Missing Missing fn copack<IoError>> static_assert std same_as<Union fn copack_for<IoError Missing NotANumber OutOfRange>> copack<A B> copack<B A> libfn copack LIBFN_CXX26 std type_order copack copack<B A> A B copack<A copack<C D>> copack_for copack copack copack copack_for choice choice_for copack copack_for choice_for copack choice copack copack<> copack<> copack_for<bool bool> copack<bool> copack std tuple std variant copack apply expected<T E> pack copack_for fn as_pack fn as_copack copack pack copack expected and_then