1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/*
* SPDX-License-Identifier: MIT
* Copyright (c) 2023 - 2026. The DeepCausality Authors and Contributors. All Rights Reserved.
*/
//! # The lax monoidal structure on an endofunctor: `Ο`, `Ξ·`, and the promise that they associate
//!
//! An applicative functor is a **monoid object**, in the same sense the algebra crate already uses
//! for `AddMonoid` and `MulMonoid`. Only the monoidal product differs: a monad is a monoid in
//! (End(π), β, Id), an applicative one in (End(π), β_Day, Id). This module supplies the structure
//! maps of the second, at the level of **endofunctors**.
//!
//! Not to be confused with [`SymMonoidal`](crate::SymMonoidal) in `crate::monoidal`, which is the
//! *cartesian* symmetric-monoidal PROP at the level of **values**. Both modules define a `unit`,
//! and they are different maps:
//!
//! | | level | `unit` is |
//! |---|---|---|
//! | [`SymMonoidal`](crate::SymMonoidal) | values | `Ξ· : I β A`, the [`Monoid`](deep_causality_algebra::Monoid) identity `M::empty()` |
//! | [`LaxMonoidal`] | endofunctors | `Ξ· : I β F I`, the unit *object* lifted into `F` |
//!
//! # Why `pure` is not here
//!
//! A lax monoidal functor is `(F, Ο, Ξ·)` with `Ξ· : I β F I` and `Ο : F A β F B β F (A β B)`. The
//! Day-monoid presentation instead gives `Ξ· : Id β F`, whose component at `a` is `a -> F a`, which
//! is exactly [`Pure`](crate::Pure). Going from the first to the second needs the **diagonal**
//! `Ξ : A β A β A`, because `pure(a) = fmap(Ξ·(), |()| a)` calls the constant function once per
//! slot.
//!
//! A category with a diagonal is cartesian; one with only `β` is merely monoidal. Haskell's is
//! cartesian, so the two presentations coincide there and the question never arises. Rust's move
//! semantics are not cartesian, and `Clone` is the diagonal β which this crate already says, in
//! [`SymMonoidal::copy`](crate::SymMonoidal::copy), whose signature is `copy<A: Clone>(a) -> (A, A)`
//! under a citation to T. Fox, "Coalgebras and Cartesian Categories," *Comm. Algebra* 4(7), 1976.
//!
//! So `pure` is a cartesian convenience rather than part of the monoid structure, and the traits
//! here require no `Clone` of anything. See
//! `openspec/notes/archive/hkt_gat/monoidal-applicative.md` for the measurements behind that.
//!
//! # Why `Ο` and `Ξ·` are split across two traits
//!
//! Every context-carrying witness in this workspace has a lawful `Ο` and no lawful `Ξ·`. `pure(a)`
//! at least receives a value; `unit()` receives nothing and must still name a complex, a grade, a
//! lattice or an adjacency map. Bundling them would exclude that whole family from a structure it
//! otherwise supports, and push it toward writing an unlawful `unit`. [`Semigroupal`] carries `Ο`
//! alone, which is all [`MonoidalApplicative::apply`] needs; [`LaxMonoidal`] adds `Ξ·`, which is
//! needed only to *state* the unit laws.
//!
//! # Laws
//!
//! Machine-checked in `lean/DeepCausalityFormal/Haft/LaxMonoidal.lean` and witnessed in
//! `deep_causality_unified_math/deep_causality_haft/tests/formalization_lean/lax_monoidal_tests.rs`.
//!
//! Laws are stated for pure functions; a stateful `FnMut` closure voids them.
use crate::;
/// The semigroupal structure: the monoid multiplication `Ο` on its own, with no unit.
///
/// `zip_with` is the required method and `zip` is derived from it.
///
/// That ordering was once forced. Deriving [`apply`](MonoidalApplicative::apply) through `zip`
/// builds an `F::Type<(Func, A)>` and hands it to [`fmap`](Functor::fmap), and while every
/// method carried a `T: Satisfies<F::Constraint>` bound, the *tuple* had to satisfy the witness
/// constraint too. That bound then leaked into every function generic over the witness.
/// `Satisfies` and the associated `Constraint` are gone, so `zip` now carries no bounds and the
/// two are interderivable. `zip_with` stays the required method because it is the one that
/// allocates nothing: it pairs and combines in a single pass, where `zip` must materialise a
/// tuple the caller may only take apart again.
/// The same shape appears twice elsewhere in the workspace: [`MonoidalMerge::merge`] at the
/// `HKT3Unbound` level, and `LatticeGaugeFieldWitness::zip_with` concretely in
/// `deep_causality_topology`, which returns `Result` because its `Ο` is partial.
///
/// # Laws
///
/// 1. **Naturality**: `zip(fmap(fa, f), fmap(fb, g)) == fmap(zip(fa, fb), |(a, b)| (f(a), g(b)))`
/// 2. **Associativity**: `zip(zip(fa, fb), fc) β
zip(fa, zip(fb, fc))`, modulo the associator
/// `((A, B), C) β
(A, (B, C))`
///
/// Associativity is a *promise*, not a consequence of the signature. A witness records it by
/// implementing [`Convolutional`].
///
/// [`MonoidalMerge::merge`]: crate::MonoidalMerge::merge
/// The full lax monoidal structure: [`Semigroupal`]'s `Ο` plus the unit `Ξ·`.
///
/// # When a witness must *not* implement this
///
/// `unit` takes no argument and must still return an inhabited `F::Type<()>`. A witness whose
/// carrier needs a simplicial complex, a grade, a lattice, a shape or an adjacency map cannot
/// supply one without inventing it, and an invented context does not satisfy the unit laws: it
/// fails at every real value rather than in some corner. Such a witness implements
/// [`Semigroupal`] alone.
///
/// This is not hypothetical. A deleted `GaugeField` [`MonoidalMerge`] impl in this workspace did
/// fabricate its unit, and five tests were written that asserted the resulting defect as the
/// specification.
///
/// # Laws
///
/// In addition to [`Semigroupal`]'s:
///
/// 3. **Left unit**: `fmap(zip(unit(), fa), |((), a)| a) == fa`
/// 4. **Right unit**: `fmap(zip(fa, unit()), |(a, ())| a) == fa`
///
/// [`MonoidalMerge`]: crate::MonoidalMerge
/// Marker. Promises that `ΞΌ` associates under **composition**: a monoid object in (End(π), β, Id).
///
/// The promise is the monad associativity law,
/// `bind(bind(m, f), g) == bind(m, |x| bind(f(x), g))`. The compiler cannot check it, so
/// implementing this trait is an assertion by the developer.
///
/// # Never handed out by inference
///
/// This trait SHALL NOT be blanket-implemented, derived, or implied by any other trait. Each impl
/// is one line naming one witness, following
/// [`Associative`](deep_causality_algebra::Associative), whose documentation records why a marker
/// carrying an unverifiable promise cannot be granted by inference: a downstream type would
/// silently acquire a law nobody promised. The *absence* of this marker on a witness is therefore
/// readable as a deliberate withholding.
///
/// # Holding both markers
///
/// A witness carrying both this and [`Convolutional`] owes the applicative-monad coherence law,
/// `apply(f_ab, f_a) == bind(f_ab, |f| fmap(f_a, f))`, proved as `haft.monad.applicative_coherence`
/// and discharged by a law test naming the witness.
/// Marker. Promises that `Ο` associates under **Day convolution**: a monoid object in
/// (End(π), β, Id).
///
/// The promise is `zip(zip(a, b), c) β
zip(a, zip(b, c))` up to reassociation, together with the
/// naturality of `Ο`. The compiler cannot check either, so implementing this trait is an assertion
/// by the developer.
///
/// Carries the same no-inference discipline as [`Compositional`], and the same coherence obligation
/// when a witness holds both.
/// The applicative structure that comes from the monoid: `apply` derived from `Ο`, free of the
/// diagonal.
///
/// # Why this is a sibling of [`Applicative`](crate::Applicative) rather than a replacement
///
/// There are two routes to an applicative and they differ exactly on whether they need `Clone`.
/// The monoidal route pairs slot with slot and consumes nothing twice. The monadic route induces
/// `ap(ff, fa) = bind(ff, |f| fmap(fa, f))`, which re-runs the continuation once per function and
/// therefore consumes `fa` many times.
///
/// `VecWitness` is on the second route and cannot move: its `apply` is the cartesian list
/// applicative, pinned as the only lawful choice by `haft.monad.applicative_coherence`, and it
/// needs `Func: Clone`. `ZipList` is not an escape, because the unit of a positional zip is the
/// infinite repeat and a finite `Vec` cannot represent it. So [`Applicative`](crate::Applicative)
/// keeps its signature, its `A: Clone` bound and all of its impls, and this trait sits beside it.
/// A witness may hold both, and then owes a law test that the two `apply`s agree.
///
/// # Laws
///
/// Those of [`Semigroupal`] and, where the witness is also [`LaxMonoidal`], the unit laws. The
/// four McBrideβPaterson laws remain stated on [`Applicative`](crate::Applicative); they are not
/// restated here, because the monoid coherence conditions alone do not pin a witness's applicative
/// (both the function-major and argument-major cartesian products on `Vec` satisfy all of them).
/// # The gate is load-bearing
///
/// A witness carrying the full structure but withholding the promise cannot reach `apply`.
///
/// ```compile_fail
/// use deep_causality_haft::{
/// Convolutional, Functor, HKT, MonoidalApplicative, Semigroupal,
/// };
///
/// pub struct Unpromised;
/// impl HKT for Unpromised {
/// type Type<T> = Vec<T>;
/// }
/// impl Functor<Unpromised> for Unpromised {
/// fn fmap<A, B, Func>(fa: Vec<A>, f: Func) -> Vec<B>
/// where
/// Func: FnMut(A) -> B,
/// {
/// fa.into_iter().map(f).collect()
/// }
/// }
/// impl Semigroupal<Unpromised> for Unpromised {
/// fn zip_with<A, B, C, Func>(fa: Vec<A>, fb: Vec<B>, mut f: Func) -> Vec<C>
/// where
/// Func: FnMut(A, B) -> C,
/// {
/// fa.into_iter().zip(fb).map(|(a, b)| f(a, b)).collect()
/// }
/// }
///
/// // No `impl Convolutional<Unpromised> for Unpromised {}` β the promise is withheld, so this
/// // fails with an unsatisfied `Convolutional` bound.
/// impl MonoidalApplicative<Unpromised> for Unpromised {}
/// ```
///
/// Adding the withheld line makes the same code compile:
///
/// ```rust
/// use deep_causality_haft::{
/// Convolutional, Functor, HKT, MonoidalApplicative, Semigroupal,
/// };
///
/// pub struct Promised;
/// impl HKT for Promised {
/// type Type<T> = Vec<T>;
/// }
/// impl Functor<Promised> for Promised {
/// fn fmap<A, B, Func>(fa: Vec<A>, f: Func) -> Vec<B>
/// where
/// Func: FnMut(A) -> B,
/// {
/// fa.into_iter().map(f).collect()
/// }
/// }
/// impl Semigroupal<Promised> for Promised {
/// fn zip_with<A, B, C, Func>(fa: Vec<A>, fb: Vec<B>, mut f: Func) -> Vec<C>
/// where
/// Func: FnMut(A, B) -> C,
/// {
/// fa.into_iter().zip(fb).map(|(a, b)| f(a, b)).collect()
/// }
/// }
/// impl Convolutional<Promised> for Promised {}
/// impl MonoidalApplicative<Promised> for Promised {}
///
/// let add: fn(i32) -> i32 = |x| x + 10;
/// assert_eq!(Promised::apply(vec![add, add], vec![1, 2]), vec![11, 12]);
/// ```