Skip to content
Sjoerd Visscher edited this page Sep 30, 2026 · 5 revisions

The laws proarrow states as code, drawn as string diagrams. Each law is an equation between two ways of building an arrow, and each picture draws both sides exactly as the law builds them, without simplifying either one. So where a law says two different constructions agree, you see two different pictures next to each other.

The object variables of a law are single wires, labelled a to e, and the arbitrary arrows a law asks for are boxes with the names the law gives them. In the profunctor sections at the end, the elements a law is about are shaded boxes named p, p′ and p″ and the wires go up to f. Copying and merging are drawn as points, a dual wire is drawn hollow and labelled with ⁻¹, the unit is a dotted wire labelled I, and a trace is a loop round the side.

The pictures are made by Proarrow.Tools.Diagrams.Svg, which lays each diagram out from how it is built: a tensor puts its sides next to each other, a composite stacks them with a band of wires in between, and a trace draws its loops. Some sections are drawn with options that show more of the structure; the code under each heading says which.

Category · Monoidal · Symmetric monoidal · Traced · *-autonomous · Closed · Isomix · Compact closed · Monoids · Comonoids · Copy and discard · Frobenius · Monoidal profunctor · Strong · Costrong

Category

Identities are units for composition, which is associative. Drawn with explicit identities, so each id is a dashed frame; associativity draws the same on both sides, as a string diagram does not record how a composite was bracketed.

lawSvgsWith @'[CategoryOf] defaultOptions{explicitIdentities = True}

left identity
left identity
right identity
right identity
associativity
associativity

Monoidal

Unitors and associator are invertible and natural, the tensor is a bifunctor, and the triangle and pentagon commute. Drawn with explicit coherence. The unit is a wire of its own, drawn dotted and labelled 𝐈, so a unitor is a unit wire running into another wire or out of it. The associator is drawn with brackets: at the top the pair grouped in its input, at the bottom the pair grouped in its output. Without explicit coherence, both sides of these laws draw the same. Tensor interchange draws the same either way: that string diagrams do not tell the two apart is what the law says.

lawSvgsWith @'[Monoidal] defaultOptions{explicitCoherence = True}

leftUnitor left inverse
leftUnitor left inverse
leftUnitor right inverse
leftUnitor right inverse
rightUnitor left inverse
rightUnitor left inverse
rightUnitor right inverse
rightUnitor right inverse
associator left inverse
associator left inverse
associator right inverse
associator right inverse
tensor identity
tensor identity
tensor interchange
tensor interchange
leftUnitor naturality
leftUnitor naturality
leftUnitorInv naturality
leftUnitorInv naturality
rightUnitor naturality
rightUnitor naturality
rightUnitorInv naturality
rightUnitorInv naturality
associator naturality
associator naturality
associatorInv naturality
associatorInv naturality
triangle identity
triangle identity
pentagon identity
pentagon identity

Symmetric monoidal

The swap undoes itself, is natural, and satisfies the hexagon. Drawn with explicit swaps, so each swap is a crossing of its own; without them, a swap only moves wires and most of these draw the same.

lawSvgsWith @SymMonoidalStructures defaultOptions{explicitSwaps = True}

swap self-inverse
swap self-inverse
swap naturality
swap naturality
hexagon identity
hexagon identity

Traced

The trace of f over u feeds its u output back to its u input, drawn as a loop round the side. It is natural in the other wires, slides along the loop, is trivial over the unit and nests over a tensor, lets a wire run past, and turns a swap into a plain wire. Drawn with explicit coherence, so the trace over the unit is a dotted loop and the regroupings the nested traces need show as brackets.

lawSvgsWith @TracedStructures defaultOptions{explicitCoherence = True}

naturality
naturality
sliding
sliding
vanishing (unit)
vanishing (unit)
vanishing (tensor)
vanishing (tensor)
superposing
superposing
yanking
yanking

*-autonomous

Duals and linear distribution. The dual of a wire is a wire of its own, labelled with ⁻¹ and drawn hollow. A wire is bent with a cup or a cap, drawn as one bend: the half that runs backwards is the dual wire, and the style switches at the apex. Double negation is only a relabelling here, so its inverse laws are straight wires; the definition law compares it with the one derived from linDist and the duality unit.

lawSvgs @StarAutonomousStructures

dual identity
dual identity
dual composition
dual composition
linDist naturality
linDist naturality
dual left inverse
dual left inverse
dual right inverse
dual right inverse
linDist left inverse
linDist left inverse
linDist right inverse
linDist right inverse
doubleNegInv definition
doubleNegInv definition
doubleNeg left inverse
doubleNeg left inverse
doubleNeg right inverse
doubleNeg right inverse

Closed

Currying and apply. The exponential is the *-autonomous one, the dual of a ⊗ b⁻¹, so curry bends a wire round, and the part running backwards is a dual wire.

lawSvgs @ClosedStructures

curry left inverse
curry left inverse
curry right inverse
curry right inverse
curry naturality
curry naturality
internal hom on arrows
internal hom on arrows

Isomix

The unit of par is isomorphic to the unit: dualUnit and its inverse are drawn as a relabelling of the unit wire, so both inverse laws are empty diagrams. The duality counit joins a dual and its wire into the unit, drawn as one bend; its definition law compares it with the one derived from the *-autonomous structure, which goes into the unit of par first.

lawSvgs @IsoMixStructures

dualUnit left inverse
dualUnit left inverse
dualUnit right inverse
dualUnit right inverse
dualityCounit definition
dualityCounit definition

Compact closed

The dual distributes over the tensor, and the zigzag identities hold, with the duality unit and counit drawn as one bend each, so a zigzag is a wire bent up and down again, dual on its middle stretch. The definition law compares the unit with the one derived from the *-autonomous structure; the counit comes from the isomix structure.

lawSvgs @CompactClosedStructures

distribDual left inverse
distribDual left inverse
distribDual right inverse
distribDual right inverse
dualityUnit definition
dualityUnit definition
zigzag (a)
zigzag (a)
zigzag (Dual a)
zigzag (Dual a)

Monoids

Every object is a monoid: the unit point is a unit for the merge point, which is associative, and commutative when the monoids are commutative ones. The unit laws are drawn with explicit coherence, so they show the unitor they equal.

lawSvgsWith @'[Monoidal, Supplies Monoid] defaultOptions{explicitCoherence = True}
lawSvgs @'[Monoidal, SymMonoidal, Supplies CommutativeMonoid]

left unit
left unit
right unit
right unit
associativity
associativity
commutativity
commutativity

Comonoids

Every object is a comonoid: the discard point is a counit for the copy point, which is coassociative, and cocommutative when the comonoids are cocommutative ones. The counit laws are drawn with explicit coherence.

lawSvgsWith @'[Monoidal, Supplies Comonoid] defaultOptions{explicitCoherence = True}
lawSvgs @'[Monoidal, SymMonoidal, Supplies CocommutativeComonoid]

left counit
left counit
right counit
right counit
coassociativity
coassociativity
cocommutativity
cocommutativity

Copy and discard

A copy-discard category copies and discards with its supplied comonoids, and these respect the tensor: copying or discarding a pair is copying or discarding both parts, and on the unit they do nothing. Drawn with explicit coherence, so the unit wire and the regrouping show.

lawSvgsWith @CopyDiscardStructures defaultOptions{explicitCoherence = True}

copy is comult
copy is comult
discard is counit
discard is counit
copy of a tensor
copy of a tensor
discard of a tensor
discard of a tensor
copy of the unit
copy of the unit
discard of the unit
discard of the unit

Frobenius

The monoids and comonoids together are special Frobenius algebras: a copy then a merge is the identity, and the Frobenius law holds. These are the spiders that make every other bend here work.

lawSvgs @FrobeniusStructures

speciality
speciality
Frobenius (left)
Frobenius (left)
Frobenius (right)
Frobenius (right)

Monoidal profunctor

A monoidal profunctor puts elements side by side with **, with one as its unit. The unit laws and associativity hold up to the unitors and the associator, and ** is natural. The profunctor is drawn as the identity profunctor on diagrams, so an element is a shaded box. Drawn with explicit coherence.

proLawSvgsWith @MonoidalProfunctor defaultOptions{explicitCoherence = True}

left unit
left unit
right unit
right unit
associativity
associativity
** naturality
** naturality

Strong

Strength for the tensor: act puts a wire next to an element. Acting with the unit or with a tensor is the unitor or the associator, act is natural in the element, and an arrow on the extra wire can go above the element or below it. Drawn with explicit coherence.

proLawSvgsWith @(Strong Tensor) defaultOptions{explicitCoherence = True}

act unit
act unit
act tensor
act tensor
act naturality
act naturality
act dinaturality
act dinaturality

Costrong

Costrength for the tensor: coact feeds wires of an element back as a loop, as a trace does. An element with tensored ends is made from p with arbitrary arrows g and h around it. Coacting is natural, an arrow slides along the loop, and coacting with the unit or with a tensor is trivial or nests. Drawn with explicit coherence.

proLawSvgsWith @(Costrong Tensor) defaultOptions{explicitCoherence = True}

coact unit
coact unit
coact tensor
coact tensor
coact naturality
coact naturality
coact sliding
coact sliding

Clone this wiki locally