Functor#

class discopy.cat.Functor(ob=None, ar=None, cod=None)[source]#

Bases: Composable[Category]

A functor is a pair of maps ob and ar and an optional codomain category cod.

Parameters
  • ob (Mapping[Ob, Ob] | Callable[[Ob], Ob] | None) – Mapping from Ob to cod.ob.

  • ar (Mapping[Box, Arrow] | Callable[[Box], Arrow] | None) – Mapping from Box to cod.ar.

  • cod (T) – The codomain, Category(Ob, Arrow) by default.

Example

>>> x, y, z = Ob('x'), Ob('y'), Ob('z')
>>> f, g = Box('f', x, y), Box('g', y, z)
>>> ob, ar = {x: y, y: z, z: y}, {f: g, g: g[::-1]}
>>> F = Functor(ob, ar)
>>> assert F(x) == y and F(f) == g

Tip

Both ob and ar can be a function rather than a dictionary. In conjunction with Box.data, this can be used to create a Functor from a free category with infinitely many generators.

>>> ob = lambda x: x
>>> ar = lambda f: Box(f.name, f.dom, f.cod, data=f.data + 1)
>>> F = Functor(ob, ar)
>>> h = Box('h', x, x, data=42)
>>> assert F(h).data == 43 and F(F(h)).data == 44

If Box.data is a mutable object, then so can be the image of a Functor on it.

>>> ar = lambda f: f if all(f.data) else f[::-1]
>>> F = Functor(ob, ar)
>>> m = Box('m', x, x, data=[True])
>>> assert F(m) == m
>>> m.data.append(False)
>>> assert F(m) == m[::-1]
classmethod id(dom=None)[source]#

The identity functor on a given category dom.

Parameters

dom (Optional[Category]) – The domain of the functor.

Return type

Functor

then(other)[source]#

The composition of functor with another.

Parameters

other (Functor) – The other functor with which to compose.

Return type

Functor

Note

Functor composition is unital only on the left. Indeed, we cannot check equality of functors defined with functions instead of dictionaries.

Example

>>> x, y = Ob('x'), Ob('y')
>>> F, G = Functor({x: y}, {}), Functor({y: x}, {})
>>> print(F >> G)
cat.Functor(ob={cat.Ob('x'): cat.Ob('x')}, ar={})
>>> assert F >> Functor.id() == F != Functor.id() >> F
>>> print(Functor.id() >> F)  
cat.Functor(ob=<function ...>, ar=...)