# Fantas, Eel, and Specification 19: Semigroupoid + Category

10 Jul 2017**It’s not goodbye**, Fantasists. We’ll have other projects, new memories, more chance encounters. Let’s end on a high: talking about the humble `Category`

, and how we’ve been learning this since the beginning. While it may not be the most *immediately useful* structure, it’s a **gem for the curious**.

Before we go any further, let’s get the **methods** and **laws** on the table. A `Semigroupoid`

has one method, called `compose`

:

```
compose :: Semigroupoid c
=> c i j
~> c j k
-> c i k
```

There’s also one **law**, which is going to look *boringly* familiar:

```
// Associativity..
a.compose(b.compose(c)) ===
a.compose(b).compose(c)
```

A `Category`

is a `Semigroupoid`

with **one new method**:

```
id :: Category c => () -> c a a
```

Now, if you’ve been following the series, there are no prizes for guessing the two laws that come with this:

```
// Left and right identity!
a === C.id().compose(a)
=== a.compose(C.id())
```

Yep, it’s another `Monoid`

-looking structure. Let’s all **pretend to be surprised**.

*Now*, there’s a reason to get excited about these things. You may not **directly** interact with them every day, but they’re *everywhere* underneath the surface:

```
Function.prototype.compose =
function (that) {
return x => that(this(x))
}
Function.id = () => x => x
```

Yep. Under function **composition**, our functions form a `Category`

! Do notice that `Function#compose`

is defined the exact same way as `Function#map`

, too. Of course, this might be a bit easier to introduce to your codebase than `Function#map`

:

```
// Much more colleague-friendly?
const app =
readInput
.compose(clean)
.compose(capitalise)
.compose(etCetera)
```

We can think of `s a b`

(for some `Semigroupoid s`

) as “a relationship from `a`

to `b`

” (the set of which, in **fancy talk**, are called **morphisms**), and `Category`

types as having “an identity relationship”. When we did the deep dive with `Monad`

, we actually looked at another `Category`

:

```
//- We need a TypeRep for M to do `id`.
//- Note that, for a `Chain` type, we could
//- only make a `Semigroupoid`, not a
//- `Category`!
const MCompose = M => {
//+ type MCompose m a b = a -> m b
const MCompose_ = daggy.tagged('f')
//+ compose :: Chain m
//+ => MCompose m a b
//+ ~> MCompose m b c
//+ -> MCompose m a c
MCompose_.prototype.compose =
function (that) {
return x => this.f(x).chain(that.f)
}
//+ id :: Monad m => () -> MCompose m a a
MCompose_.id = () => MCompose_(M.of)
return MCompose_
}
```

Note that we originally wrote a `Monoid`

for operations `a -> m a`

. With a `Category`

, we can talk about operations `a -> m b`

, and we have much more **freedom**. Symmetrically, our `Comonad`

friends give us an almost identical `Category`

:

```
//- Extend for Semigroupoid, Comonad for
//- Category!
//+ type WCompose w a b = w a -> b
const WCompose = daggy.tagged('f')
//+ compose :: Extend w
//+ => (w a -> b)
//+ ~> (w b -> c)
//+ -> (w a -> c)
WCompose.prototype.compose =
function (that) {
return x => this.f(x).extend(that.f)
}
//+ id :: Comonad w => () -> WCompose w a a
WCompose.id = () =>
WCompose(x => x.extract())
```

Why limit ourselves? We have **composition**! Let’s turn the `Applicative`

’s composition into a `Category`

:

```
//+ Apply for Semigroupoid, Applicative for
//+ Category!
const ApCompose = (A, C) => {
//+ type ApCompose f c a b = f (c a b)
const ApCompose_ = daggy.tagged('f')
//+ compose :: Apply f
//+ => Semigroupoid s
//+ => f s a b
//+ ~> f s b c
//+ -> f s a c
ApCompose_.prototype.compose =
function (that) {
return that.f.ap(this.f.map(
x => y => x.compose(y)))
}
//+ id :: Applicative f
//+ => Category s
//+ => () -> f s a a
ApCompose_.id = () => A.of(C.id())
}
```

The really **neat** thing here is that, instead of limiting ourselves to the `Category`

of *functions* within `Applicative`

context, we’ve generalised `Function`

to `Category`

! It’s all getting a bit **abstract** and **scary**, right? **Don’t panic**.

With the **helpful exception** of `Function`

, these examples may all seem a bit impractical. *Granted*, you might find that `MCompose#compose`

gives you a nice, declarative way to chain together **monadic actions**, or something to that effect, but this largely seems a bit too… well, **abstract**!

While this *may* not be the one you use every day, the `Semigroupoid`

and `Category`

structures form a *very* important idea. We hinted at this earlier: * Category is like a Monoid with *. Well, if everything we’ve seen ended up looking like

**more freedom**

`Semigroup`

or `Monoid`

… effectively, the **base concept**been

`Category`

all along!I had originally wanted to show

`Monoid`

in terms of`Category`

. Let’s just say thepage of required declarationscompiled with thehelp of three other peoplemade me think that, ifIcouldn’t understand it, I probably shouldn’t put it here!

It’s not *crucial* that we understand why. Discussion around categories leads me to **all sorts** of headaches, and to no avail. What is important is that I make a **small confession**…

*This entire series has been about a branch of maths called Category Theory: the theory of categories*.

**Blam**! Here in programmer land, using our shiny new structures to write **fault-tolerant database systems** and **reactive event streams**, we thought we were safe from maths… but **no**! The whole **purpose** of Fantasy Land is to utilise concepts from category theory that help us to write **safer code**. “Was `Functor`

maths?” *I’m afraid so*. “Surely our `Semigroup`

was innocent, though?” *I wish I could tell you so*. “Not `Alt`

though, right? … Right?” *All category theory. Please stop asking.*

Perhaps you’ll never need to think about `Category`

again, and that’s **fine**. Function composition is more than valuable enough to justify its existence. *However*, sooner or later, if you continue down this **rabbit hole**, you’ll start asking **why** and **how**, and I’m sure you’ll find your way back here…

Simply, there’s really not much (immediately practical) to say about `Category`

and `Semigroupoid`

at this level of generality, but it’s a neat little concept, and I thought it was nice to put a name to the pattern we’ve been seeing **all the time**! Next time you define a weird type of **relationship** (perhaps one involving `Monad`

?), give a thought to the humble `Category`

we’ve just seen, and see whether you can simplify your code with a more specific `compose`

implementation.

The keen-eyed among you will have noticed that this is **the last Fantasy Land structure**, and that we’ve really come to **the end of the series**. Well… **don’t panic**! I have **one more** article to publish before we call this whole thing a day. Call it the *encore* that no one wanted.

On that note, next time, we’ll be talking about **bringing concepts together** to build some cool little projects, and where you can go next! Otherwise, **thank you so much** for reading through

**at least**19 pages of my mindless rambling, and I hope that it has been useful in some small way.

Now, **write beautiful JavaScript**.

♥ ♥ ♥