Monads

Monad definitions with units, multiplications, and monad laws.

monads

Monads and Kleisli categories on V-enriched FinSet.

A monad (T, η, μ) consists of an endofunctor T, a unit η: Id ⇒ T, and a multiplication μ: T² ⇒ T satisfying:

μ ∘ T(μ) = μ ∘ μ_T    (associativity)
μ ∘ η_T = id           (left unit)
μ ∘ T(η) = id          (right unit)

The Kleisli category of a monad has the same objects but morphisms A → B are morphisms A → T(B) in the base category, composed via:

f >=> g = μ_C ∘ T(g) ∘ f

This module provides:

Monad (abstract)
├── FuzzyPowersetMonad — Kleisli category = FuzzyRel
└── FreeMonoidMonad    — Kleisli category = string-valued relations

KleisliCategory — wraps a monad for composition

Monad

Bases: ABC

Abstract monad (T, η, μ) on V-enriched FinSet.

Subclasses must implement endofunctor, unit, and multiply. Kleisli composition is derived.

endofunctor abstractmethod property

endofunctor: Functor

The underlying endofunctor T.

unit abstractmethod

unit(obj: SetObject) -> Morphism

The unit component η_A: A → T(A).

PARAMETER DESCRIPTION
obj

The object A.

TYPE: SetObject

RETURNS DESCRIPTION
Morphism

The unit morphism η_A.

Source code in src/quivers/monadic/monads.py
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
@abstractmethod
def unit(self, obj: SetObject) -> Morphism:
    """The unit component η_A: A → T(A).

    Parameters
    ----------
    obj : SetObject
        The object A.

    Returns
    -------
    Morphism
        The unit morphism η_A.
    """
    ...

multiply abstractmethod

multiply(obj: SetObject) -> Morphism

The multiplication component μ_A: T(T(A)) → T(A).

PARAMETER DESCRIPTION
obj

The object A.

TYPE: SetObject

RETURNS DESCRIPTION
Morphism

The multiplication morphism μ_A.

Source code in src/quivers/monadic/monads.py
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
@abstractmethod
def multiply(self, obj: SetObject) -> Morphism:
    """The multiplication component μ_A: T(T(A)) → T(A).

    Parameters
    ----------
    obj : SetObject
        The object A.

    Returns
    -------
    Morphism
        The multiplication morphism μ_A.
    """
    ...

kleisli_compose

kleisli_compose(f: Morphism, g: Morphism) -> Morphism

Kleisli composition: f >=> g = μ_C ∘ T(g) ∘ f.

For f: A → T(B) and g: B → T(C), produces A → T(C).

PARAMETER DESCRIPTION
f

Left Kleisli morphism A → T(B).

TYPE: Morphism

g

Right Kleisli morphism B → T(C).

TYPE: Morphism

RETURNS DESCRIPTION
Morphism

Composed Kleisli morphism A → T(C).

Source code in src/quivers/monadic/monads.py
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
def kleisli_compose(self, f: Morphism, g: Morphism) -> Morphism:
    """Kleisli composition: f >=> g = μ_C ∘ T(g) ∘ f.

    For f: A → T(B) and g: B → T(C), produces A → T(C).

    Parameters
    ----------
    f : Morphism
        Left Kleisli morphism A → T(B).
    g : Morphism
        Right Kleisli morphism B → T(C).

    Returns
    -------
    Morphism
        Composed Kleisli morphism A → T(C).
    """
    tg = self.endofunctor.map_morphism(g)
    f_then_tg = f >> tg
    mu = self._multiply_at_codomain(g)
    return f_then_tg >> mu

KleisliCategory

KleisliCategory(monad: Monad)

The Kleisli category of a monad.

Objects are the same as the base category. Morphisms A → B in the Kleisli category are morphisms A → T(B) in the base category.

PARAMETER DESCRIPTION
monad

The underlying monad.

TYPE: Monad

Source code in src/quivers/monadic/monads.py
123
124
def __init__(self, monad: Monad) -> None:
    self._monad = monad

monad property

monad: Monad

The underlying monad.

identity

identity(obj: SetObject) -> Morphism

Kleisli identity at object A: η_A: A → T(A).

PARAMETER DESCRIPTION
obj

The object A.

TYPE: SetObject

RETURNS DESCRIPTION
Morphism

The Kleisli identity morphism.

Source code in src/quivers/monadic/monads.py
131
132
133
134
135
136
137
138
139
140
141
142
143
144
def identity(self, obj: SetObject) -> Morphism:
    """Kleisli identity at object A: η_A: A → T(A).

    Parameters
    ----------
    obj : SetObject
        The object A.

    Returns
    -------
    Morphism
        The Kleisli identity morphism.
    """
    return self._monad.unit(obj)

compose

compose(f: Morphism, g: Morphism) -> Morphism

Kleisli composition: f >=> g.

PARAMETER DESCRIPTION
f

Left morphism A → T(B).

TYPE: Morphism

g

Right morphism B → T(C).

TYPE: Morphism

RETURNS DESCRIPTION
Morphism

Composed morphism A → T(C).

Source code in src/quivers/monadic/monads.py
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
def compose(self, f: Morphism, g: Morphism) -> Morphism:
    """Kleisli composition: f >=> g.

    Parameters
    ----------
    f : Morphism
        Left morphism A → T(B).
    g : Morphism
        Right morphism B → T(C).

    Returns
    -------
    Morphism
        Composed morphism A → T(C).
    """
    return self._monad.kleisli_compose(f, g)

FuzzyPowersetMonad

FuzzyPowersetMonad(quantale: Quantale | None = None)

Bases: Monad

The fuzzy powerset monad with a given quantale.

At the set level, T(A) = A because fuzzy subsets are represented as membership function tensors, not as elements of a powerset. The unit η_A = identity(A) and the multiplication μ_A = identity(A).

The Kleisli composition f >=> g reduces to quantale.compose(f, g), which is exactly the >> operator on morphisms.

PARAMETER DESCRIPTION
quantale

The enrichment algebra. Defaults to PRODUCT_FUZZY.

TYPE: Quantale or None DEFAULT: None

Source code in src/quivers/monadic/monads.py
180
181
def __init__(self, quantale: Quantale | None = None) -> None:
    self._quantale = quantale if quantale is not None else PRODUCT_FUZZY

quantale property

quantale: Quantale

The enrichment algebra.

endofunctor property

endofunctor: Functor

T = Id (identity functor at set level).

unit

unit(obj: SetObject) -> Morphism

η_A = identity(A): Kronecker delta.

Source code in src/quivers/monadic/monads.py
193
194
195
def unit(self, obj: SetObject) -> Morphism:
    """η_A = identity(A): Kronecker delta."""
    return identity(obj, quantale=self._quantale)

multiply

multiply(obj: SetObject) -> Morphism

μ_A = identity(A): union of fuzzy sets.

Source code in src/quivers/monadic/monads.py
197
198
199
def multiply(self, obj: SetObject) -> Morphism:
    """μ_A = identity(A): union of fuzzy sets."""
    return identity(obj, quantale=self._quantale)

kleisli_compose

kleisli_compose(f: Morphism, g: Morphism) -> Morphism

Kleisli composition = V-enriched composition via >>.

Source code in src/quivers/monadic/monads.py
201
202
203
def kleisli_compose(self, f: Morphism, g: Morphism) -> Morphism:
    """Kleisli composition = V-enriched composition via >>."""
    return f >> g

FreeMonoidMonad

FreeMonoidMonad(max_length: int)

Bases: Monad

The free monoid monad, truncated to max_length.

T(A) = FreeMonoid(generators=A, max_length=max_length) = 1 + A + A² + ... + A^max_length. η_A: A → A embeds each element as a length-1 word. μ_A: (A) → A flattens nested words by concatenation (truncated to max_length).

PARAMETER DESCRIPTION
max_length

Maximum string length for the truncated free monoid.

TYPE: int

Source code in src/quivers/monadic/monads.py
226
227
228
def __init__(self, max_length: int) -> None:
    self._max_length = max_length
    self._functor = FreeMonoidFunctor(max_length)

max_length property

max_length: int

Maximum string length.

endofunctor property

endofunctor: Functor

T = FreeMonoidFunctor(max_length).

unit

unit(obj: SetObject) -> Morphism

η_A: A → A* embeds each element as a length-1 word.

The tensor has shape (|A|, |A*|) with 1 at positions (a, offset_1 + a) and 0 elsewhere.

Source code in src/quivers/monadic/monads.py
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
def unit(self, obj: SetObject) -> Morphism:
    """η_A: A → A* embeds each element as a length-1 word.

    The tensor has shape (|A|, |A*|) with 1 at positions
    (a, offset_1 + a) and 0 elsewhere.
    """
    if not isinstance(obj, FinSet):
        raise TypeError(
            f"FreeMonoidMonad.unit requires FinSet, got {type(obj).__name__}"
        )
    fm = FreeMonoid(generators=obj, max_length=self._max_length)
    n = obj.cardinality
    data = torch.zeros(n, fm.size)
    offset = fm.offset(1)
    for a in range(n):
        data[a, offset + a] = 1.0
    return observed(obj, fm, data)

multiply

multiply(obj: SetObject) -> Morphism

μ_A: (A) → A* flattens nested words by concatenation.

A word in (A) at stratum k is a k-tuple of words in A*. Flattening concatenates them. If the total length exceeds max_length, the entry is 0 (truncation).

Source code in src/quivers/monadic/monads.py
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
def multiply(self, obj: SetObject) -> Morphism:
    """μ_A: (A*)* → A* flattens nested words by concatenation.

    A word in (A*)* at stratum k is a k-tuple of words in A*.
    Flattening concatenates them. If the total length exceeds
    max_length, the entry is 0 (truncation).
    """
    if not isinstance(obj, FinSet):
        raise TypeError(
            f"FreeMonoidMonad.multiply requires FinSet, got {type(obj).__name__}"
        )
    fm_a = FreeMonoid(generators=obj, max_length=self._max_length)
    fm_fm_a = FreeMonoid(
        generators=FinSet(name=f"{obj.name}*", cardinality=fm_a.size),
        max_length=self._max_length,
    )
    data = torch.zeros(fm_fm_a.size, fm_a.size)
    for i in range(fm_fm_a.size):
        outer_word = fm_fm_a.decode(i)
        inner_words: list[tuple[int, ...]] = []
        for idx in outer_word:
            inner_words.append(fm_a.decode(idx))
        flat: tuple[int, ...] = ()
        for w in inner_words:
            flat = flat + w
        if len(flat) <= self._max_length:
            j = fm_a.encode(flat)
            data[i, j] = 1.0
    return observed(fm_fm_a, fm_a, data)

kleisli_compose

kleisli_compose(f: Morphism, g: Morphism) -> Morphism

Kleisli composition: f >=> g = μ_C ∘ T(g) ∘ f.

Source code in src/quivers/monadic/monads.py
288
289
290
291
292
293
def kleisli_compose(self, f: Morphism, g: Morphism) -> Morphism:
    """Kleisli composition: f >=> g = μ_C ∘ T(g) ∘ f."""
    tg = self._functor.map_morphism(g)
    f_then_tg = f >> tg
    mu = self._multiply_at_codomain(g)
    return f_then_tg >> mu