A C 20 functional programming library lets the compiler derive the static shape of a computation alongside its values Rather than collapsing failure into one wide error type tracks the precise algebraic combinations of success alternative and error states as operations are chained into expressions The library operates on two payload types and four computation carriers Product type containing all fields a tuple like data structure Canonical coproduct containing exactly one alternative a variant like disjoint set of types Computation yielding a value or empty Computation yielding success or error Never failing computation holding one of several alternatives Never failing computation yielding a single value or a Composition operations include mapping error mapping sequential monadic binding recovery conjunction simultaneous product composition disjunction simultaneous sum composition and the n ary folds and Elimination is multidispatch Member vs Pipeline Syntax Some operations are exposed in two forms Member functions e g called directly on a carrier or payload e g Pipeline functors in namespace e g applied via e g There are also pipeline functors which have no member spelling and member functions which have no pipeline spelling The carries two meanings told apart by its right operand a pipeline functor on the right feeds the carrier into that operation while another carrier on the right is disjunction explained in Sum composition with operator| disjunction Freestanding is the general multidispatch entry point it accepts any mix of scalars tuple like structures s and s unpacking products and dispatching over alternatives in a single call Do not confuse with which is a polyfill for the C 26 meant for C 20 compilers The is an extension on top of In prose we omit prefixes writing when referring to both forms or core vocabulary types generally Storage Shape vs Call Shape Although different types can behave identically during application they remain strictly distinct in memory For example and all unpack into the same call shape during but they are separate C types with distinct layouts Application does not silently convert or unify types on the storage side To illustrate these concepts the examples in this document use a reusable set of value and error types libfn libfn pack copack optional expected choice just void transform transform_error and_then or_else operator& operator| fn conjoin fn disjoin apply transform and_then apply ex transform f cp apply f fn fn transform fn and_then operator| ex | fn transform f recover fail filter inspect inspect_error discard apply apply_r apply_type operator| fn apply f args pack copack pfn apply std apply fn apply pfn apply apply transform and_then expected pack pack<A B> std tuple<A B> std pair<A B> f a b apply struct UserId struct User struct FilePath struct MaximumSize struct BlockSize struct NotANumber struct OutOfRange struct Missing auto operator< > Missing const & const default struct IoError struct BadSyntax struct UnknownKey