Conjunction evaluates independent computations succeeds only if both operands succeed values combine into a and errors union into a If both operands share the same error type the error side remains ungraded The runtime semantics are exact The result type records every error either operand can produce at runtime it holds at most one of them the leftmost failing operand s Both operands are fully constructed before runs because C evaluates operands eagerly This is an error selection rule not short circuiting the operator makes nothing lazy or parallel Conjunction over data Unlike disjunction Sum composition with operator| disjunction applies to payload types When an operand is it performs a Cartesian distribution yielding a of s A on the opposite side widens each of those s A bare is outside the algebra it fails to compile for class types and resolves to the bitwise for built in types like Conjunction dispatches on the left operand so lifting one sidesuch as enables the algebra The n ary fold operates in two modes If all arguments are computation carriers it folds them as a monadic conjunction equivalent to cascading If no arguments are carriers it conjoins them as a data level product Mixing carriers and data in a single call is ill formed Conjunction with the Identity Cluster An operand from the identity cluster The identity cluster contributes a value but never a failure Unchanged Errors Because identity cluster operands never fail they add no alternatives to the error channel A or operand preserves the fallible operand s error side plain or graded An operand contributes its uninhabited grade to the error union no active alternative is added although the resulting error channel is promoted to a graded copack Value Bundling The identity cluster operand s value conjoins with the fallible operand s value into a Unit Elision and act as the product s identity unit and are elided from the value product e g remains Choice Distribution Conjoining a with a fallible carrier distributes the coproduct through the product yielding a of s wrapped in the fallible carrier TIP Mathematical note strict monoidal structure and distribution Conjoining independent computations via models a symmetric monoidal category with as the tensor and as the unit Strictness because packs are normalized flat there are no distinct but isomorphic spellings for the coherence maps to mediate between and are the same C type as are and The associator and unitors are therefore identities and the structure is strict rather than merely coherent Symmetry for the sum it is strict too canonical ordering makes and literally the same so the braiding is an identity For the product it is not a keeps its fields ordered and undeduplicated so and are distinct types related by a genuine swap Distributivity the tensor distributes over the coproduct represented by yielding This is the Cartesian distribution of over implemented statically by a & b pack copack auto operator_and_composition fn expected<int Error> a fn expected<bool OtherError> b > void auto result a & b static_assert std same_as<decltype result fn expected<fn pack<int bool> fn copack_for<Error OtherError>>> operator& operator& copack copack pack pack pack auto test_cartesian_distribution fn copack_for<A B> ab fn copack_for<C D> cd > void Cartesian distribution of copacks A B x C D A x C A x D B x C B x D auto result1 ab & cd static_assert std same_as<decltype result1 fn copack_for<fn pack<A C> fn pack<A D> fn pack<B C> fn pack<B D>>> Cartesian distribution of a pack and a copack A x B x C D A x B x C A x B x D constexpr fn pack<A B> Pab A B auto result2 Pab & cd static_assert std same_as<decltype result2 fn copack_for<fn pack<A B C> fn pack<A B D>>> scalar & scalar AND int fn as_pack a & b fn conjoin operator& just choice expected<T copack<>> pack just<void> expected<void copack<>> expected<T E> & just<void> expected<T E> choice copack pack auto test_conjunction_with_identity_cluster fn expected<int Error> ex fn just<double> j > void Conjoining an expected with a just auto res1 ex & j static_assert std same_as<decltype res1 fn expected<fn pack<int double> Error>> Conjoining with a unit just<void> completely elides the unit auto res2 ex & fn just<void> static_assert std same_as<decltype res2 decltype ex > Conjoining a choice causes distribution inside the carrier fn choice<bool double> ch 1 5 auto res3 ex & ch static_assert std same_as< decltype res3 fn expected<fn copack_for<fn pack<int double> fn pack<int bool>> Error>> operator& pack pack<> copack pack copack pack copack libfn