For different
Associative t, we have functors
f that we can "squash", using
biretract:
t f f ~> f
This gives us the ability to squash applications of
t.
Formally, if we have
Associative t, we are enriching
the category of endofunctors with semigroup structure, turning it into
a semigroupoidal category. Different choices of
t give
different semigroupoidal categories.
A functor
f is known as a "semigroup in the (semigroupoidal)
category of endofunctors on
t" if we can
biretract:
t f f ~> f
This gives us a few interesting results in category theory, which you
can stil reading about if you don't care:
- All functors are semigroups in the semigroupoidal category
on :+:
- The class of functors that are semigroups in the semigroupoidal
category on :*: is exactly the functors that are instances of
Alt.
- The class of functors that are semigroups in the semigroupoidal
category on Day is exactly the functors that are instances of
Apply.
- The class of functors that are semigroups in the semigroupoidal
category on Comp is exactly the functors that are instances of
Bind.
Note that instances of this class are
intended to be written
with
t as a fixed type constructor, and
f to be
allowed to vary freely:
instance Bind f => SemigroupIn Comp f
Any other sort of instance and it's easy to run into problems with
type inference. If you want to write an instance that's "polymorphic"
on tensor choice, use the
WrapHBF newtype wrapper over a type
variable, where the second argument also uses a type constructor:
instance SemigroupIn (WrapHBF t) (MyFunctor t i)
This will prevent problems with overloaded instances.