
What Monoids teach us about software - adamnemecek
https://deque.blog/2017/09/13/monoids-what-they-are-why-they-are-useful-and-what-they-teach-us-about-software/
======
wyc
Here's the ELI5 of monoids used in programming that might help get the idea
across:

Conceptually, a monoid is anything that:

\- Has a "zero-value" (mempty, e.g., 0)

\- Can be "appended" together (mappend, e.g., +)

\- Has an identity with the zero-value: x + 0 == x, 0 + x == x

\- Is associative: x + y + z == (x + y) + z == x + (y + z)

This isn't limited to just arithmetic with operators like +. You can define
whole new types as monoids if they have these characteristics. For example, we
can merge together configuration files by using monoid operators (in pseudo-
code):

    
    
        -- Zero Value
        mempty == {}
    
        -- Append
        {"color": "Blue"} `mappend` {"fontSize": 12} == {"color": "Blue", "fontSize": 12}
    
        -- Identity
        {"color": "Blue"} `mappend`               {} == {"color": "Blue"}
                       {} `mappend` {"fontSize": 12} == {"fontSize": 12}
    
        -- Associativity
        {} `mappend` {"a": "b"} `mappend` {"c": "d"}
            == ({} `mappend` {"a": "b"}) `mappend` {"c": "d"}
            ==  {} `mappend` ({"a": "b"} `mappend` {"c": "d"})
    

There's no need to break out the really formal definitions if you're just
trying to get some nice working code.

Borrowing from mathematics is beneficial because we can work with structures
that have simple but useful guarantees. In Haskell, you can expect all the
above to be true for correct type instances of Monoid, without the
implementation details at hand. It's a core tenet of functional programming to
disarm complexity with simplicity.

~~~
pluma
Thanks. This is a lot more helpful for non-math geeks than the two initial
definitions in the article:

> A Monoid can be defined a tuple (M, op, e)

This definition lost me completely because I'm not even sure what "defining it
as a tuple" is meant to imply. Based on your explanation it sounds like that
is fancy talk for saying it is defined by having three properties.

> In a statically typed language, we can translate the notion of set into the
> notion of type.

The second definition again completely lost me because I'm not even sure what
"set" and "type" mean in this context and being able to "translate the notion
of set" is unhelpful when the definition using a set is the one I didn't
understand in the first place.

I'm a programmer with over a decade of professional experience. I don't
understand the article because I have no formal education in higher math nor
in anything beyond basic computer science. Your explanation proves it's
possible to explain these concepts with practical examples rather than
academic jargon.

~~~
ebola1717
> I'm not even sure what "defining it as a tuple" is meant to imply

Yeah, in a computer science situation it's needlessly obfuscatory. It's
literally just an interface with a "plus" method and an identity value.

~~~
Retra
If you keep talking like that, you'll start to lose sight of the mathematics
upon which your field was founded. Like when someone comes out with a
fantastic new theorem about posets or monoids, you're probably going to go
around thinking it doesn't bear any meaningful impact on your job.

You learn both languages. You do it because the vast majority of human
invention and ingenuity consists if acts of translation. Anyone serious about
working with computers should understand that.

~~~
pluma
Sure. Convince me that the concepts are useful and I may be willing to invest
the energy to learn the maths around it to extract more value out of it.

But I'm a professional, not a CS student. I'm already spending my free time
honing my craft and looking into new techniques and developments in software
engineering. I can't afford spending yet more time on mostly orthogonal higher
mathematics based on the hearsay of some guy on the Internet arguing it will
allow me to understand a point somewhere down the line that might make me a
better developer.

This is exactly the same thing people say who come to programming from playing
jazz music or artistic painting or figure skating. They all claim what they
did before makes them a better programmer and they're probably even right. But
that doesn't mean I should pick up figure skating as a hobby at this point.

There are many different fields related to software development that can
directly improve your performance as a developer. Not all of them are equally
to all tasks a software developer might have to perform. I think it helps to
have a mix of them, especially at the level of teams. There are times where
the UX zealot can save the day and there are times where it's the one with the
Master's degree in Metamathemagics. I wouldn't want to miss either of them,
even they're mostly oblivious to each other's specialisation.

~~~
Retra
>But I'm a professional, not a CS student.

"I get paid, I don't learn."

You want to get paid, get paid. I won't care if you fail.

I suppose Alan Turing and Charles Babbage are just shit programmers next to
you.

------
dkural
It's always amusing to watch programmers learn a tiny piece of mathematics and
turn into a totem. All those data structures would work just as fine without a
monoid formalization, and one can use all their power with no attention given
to algebraic axioms that define a monoid.

~~~
tw1010
You don't need to give names to things, but often it's useful. It can reduce
cognitive load (if you're comfortable with the terminology) and it can be
useful when communicating to other engineers. Mathematicians did their thing
without symbols (only words) a few hundred years ago, but once everyone agrees
to use them you can start worrying about higher-order problems.

~~~
rbehrends
The problem with this argument is that a monoid is one of the most basic
constructs you can find in abstract algebra. Using monoids as a shorthand for
a couple of simple axioms doesn't buy you much; heck, the shape example didn't
even have a use case for the neutral element, so all it basically said was:
"intersection is associative". Just using a whole lot more words.

Had the shapes example be modified to describe (say) a topological space via
open sets, you may have a point.

~~~
mbrock
The cool thing about algebra is that it lets you reuse concepts and
computations between elementary arithmetic and a wide range of abstract or
complex structures. It's probably true that most programs use only very simple
monoids, but look at e.g. this article to see how composition of monoids can
be a very powerful design pattern in functional programming.

[http://repository.upenn.edu/cgi/viewcontent.cgi?article=1773...](http://repository.upenn.edu/cgi/viewcontent.cgi?article=1773&context=cis_papers)

~~~
rbehrends
And the article introduces a whole lot more concepts, such as homomorphisms in
order to be sufficiently interesting. I don't say that you can't build
interesting stuff on top of monoids (I have several colleagues that are doing
just that), just that the concept of a monoid by itself isn't very interesting
or deep.

~~~
runeks
The goal of programming is to reduce all parts to such simplicity that they
become boringly simple, and thus impossible to get wrong. Concepts are only
interesting while we don’t fully understand them yet; when we’re done fully
understanding them, they become boring and we move on to the next thing. Thus,
the solution to programming is to compose programs out of boringly simple
parts, using a boringly simple method of composition.

~~~
kbenson
> The goal of programming is to reduce all parts to such simplicity that they
> become boringly simple, and thus impossible to get wrong.

No, that's a strategy to achieve a goal of programming. Programming is about
using machines that accept well defined instructions to automate processes for
people. A complex and poorly understood program that still ends up reducing
the overall amount of work required for individuals is still worthwhile, even
if not reduced to being boringly simple.

~~~
lou1306
The main selling point is that reduction and "boring simplicity" can lead to a
formally correct program, or at least one where most errors are caught by
static analysis/type checking/etc.

~~~
kbenson
I'm not saying it's not worth while, I'm just saying that it's not the goal
(in general. Some academic exercises might have goals such as that because the
point is to learn).

It's sort of like saying the goal of owning a store is to match inventory to
sales as closely as possible. That's a strategy or sub-goal towards reaching
the real goal at best, which is to make enough money that the store pays for
itself and hopefully supports the owner. Some stores don't even have
inventory, so that strategy doesn't even apply to them. Similarly, that
programming strategy may not apply well to some problems (and some problems
_cannot_ be proven formally correct, at least in whole).

My original reply was really just meant to point out that what they viewed as
the goal of programming, is really just one of many competing strategies for
producing software, and many others don't care about that at all.

------
kens
I'm not sure why it's interesting to label all these things as monoids. It
seems kind of the tail wagging the dog.

More concretely, "monoid" seems both too general and too specific to be
useful. Things that commute and things that don't commute are lumped together
as monoids, and that seems to be a much more useful distinction.

Consider the monoids described in the article. For concatenation and file
paths, order is important. On the other hand, multiplication, addition, maps,
sets, and the shape examples all commute, so the ordering a monoid gives you
is irrelevant. How does it help to consider both concatenation and addition as
monoids?

(I'm honestly trying to see the relevance of monoids.)

~~~
rbehrends
Yeah. I mean, I work in computer algebra, and these things strike me as
trivialities.

~~~
tome
"Early on, Peter Freyd wrote

> 'Perhaps the purpose of categorical algebra is to show that which is trivial
> is trivially trivial.'

"This can be taken to mean that one thing category theory does is help make
the softer bits seem utterly natural and obvious, so as to quickly get to the
heart of the matter, isolating the hard nuggets, which one may then attack
with abandon. This is an invaluable service category theory performs for
mathematics; therefore, category theory is plain good pragmatics."

[https://ncatlab.org/nlab/show/nPOV](https://ncatlab.org/nlab/show/nPOV)

I would say equally "This is an invaluable service category theory performs
for programming; therefore, category theory is plain good pragmatics."

~~~
rbehrends
Sure. Especially in abstract algebra we have a whole, complex edifice that
builds upon semigroups and monoids. But computer science doesn't have the same
edifice (or anything resembling it), so you're mostly confined to "look, this
is a monoid, isn't this neat?" and then things sort of end there. Actual use
cases for monoids as building blocks for more complex concepts are pretty rare
in computer science. And even in mathematics, the fact that (say) a ring is
also a multiplicative monoid becomes mostly irrelevant soon enough.

~~~
tome
> in abstract algebra we have a whole, complex edifice that builds upon
> semigroups and monoids. But computer science doesn't have the same edifice
> (or anything resembling it)

Have you heard of applicative functors and monads? These are part of an
edifice of concepts that builds on monoids that we do indeed have in computer
science.

~~~
rbehrends
Yes. And this is tiny compared to what's there in mathematics, limited mostly
to people who write Haskell fanfic (from Haskell proper to Scalaz), and, to be
blunt: the terminology is used more as a shibboleth than as an abstraction
tool. Contrast this with F#'s terminology ("computation expressions"), for
example. I mean, if your goal is to have adoption levels for Haskell rival
that for abstract algebra and to keep the unwashed masses out, then the more
arcane and unrelatable your terminology is for the average person, the better.

To give another example. "Strength reduction" as a compiler optimization
relies basically on the fact that the distributive laws apply to rings. Yet
you won't find a mention of rings in compiler textbooks that explain the
technique. It's unnecessary to convey the idea and confuses more than it
explains, unless you're one of the few people who already are familiar with
rings as algebraic structures.

~~~
mbrock
I don't really think mass adoption is a goal for Haskell. It's still a really
inspiring system, and I've seen it bring a lot of people into contact with the
rich traditions of pure functional programming and the use of algebra in code.
Which is pretty cool, even if some people think it's irritating when these
people write excited blog posts about a concept they find trivial, like
monads.

I linked to a paper about composing monoids to build a graphics library. For
me that particular paper was, years ago, one of the most interesting things
I'd seen on how to structure programs.

Maybe this whole experiment with using algebraic concepts in programming is a
dead end, and maybe it is even just a way for a bunch of nerds to feel smart.
But it seems like a pretty valuable tradition to me.

There probably wouldn't be "computation expressions" in F# if it hadn't been
for Moggi and the Haskell gang. Sure it's great that we can take these
concepts and rebrand them to make them nice and cuddly (although "computation
expression" is no paragon of simple english).

Blah blah blah. I'm kinda tired of the programming forum dialectics...

------
vertex-four
OK... So exactly why is it useful to me, as someone writing programs in the
real world rather than theorising about how computation works, that a list
type under concatenation and a money type under summation are monoids? Can I
actually write useful code with this knowledge?

~~~
tw1010
Sometimes learning things like this actually changes the way you think. You
might not notice it the first month you study these things, but little by
little you'll grow comfortable with it and eventually it becomes second
nature. Eventually this can help you reason about things in ways you weren't
able to before, which is useful for certain especially challenging scenarios.

~~~
vertex-four
OK, so when was the last time knowing something is a monoid helped you solve a
problem that you were having difficulty with?

~~~
tw1010
Not sure about monoids themselves. But learning about monoids was a stepping
stone towards mastering parts of pure mathematics, which has definitely
contributed to my problem solving abilities. Sometimes you need to just bite
your tongue and learn some stuff that short-term feels useless but long-term
becomes valuable.

~~~
vertex-four
Or if people are generally incapable of explaining how something they learned
has helped them solve a problem in a domain I work in/close to, perhaps it's
not that necessary to learn after all.

~~~
theoh
Here's an example of a monoidal structure used in the design of an elegant
algebra for manipulating graphs (the network-of-nodes kind)

[https://blogs.ncl.ac.uk/andreymokhov/an-algebra-of-
graphs/](https://blogs.ncl.ac.uk/andreymokhov/an-algebra-of-graphs/)

Representing graphs is a bit of a problem in Haskell, due to the difficulty of
creating/working with cyclical structures, and the previous solutions were not
really convincing. So in some ways this might be seen as a problem immutable
data purists created for themselves. (Not my opinion)

But, either way, the ability to reason about and derive algebraic models for
some problem domain is worth pursuing in general. Mathematically structured
software is a fast track to robust, reliable, verified solutions to problems.
That's propaganda but there's a fair amount of support for it.

An idea that comes up in functional programming that has a similar algebraic
quality to monoids etc. is the notion of a type which contains only one value
(usually called "Unit") and a type which contains no values ("Bottom" or _|_).
The latter is described as "uninhabited" and is used, among other things, to
usefully describe the type of a function which never returns.
[https://en.wikipedia.org/wiki/Bottom_type](https://en.wikipedia.org/wiki/Bottom_type)

Unit represents a value which is like a point in a space which contains only
one point. It gets used to send signals with no content. For example, in
predecessors of Go, there's the pattern of sending on a "channel of unit" as a
way to essentially indicate an event to the receiver. Obviously in that use
case, a type with any distinguishable values would be superfluous.

~~~
Koshkin
Interesting, although I am not sure how Unit and Bottom are related to
monoids. Also, how does this translate, say, into C or C++? Unit is easy:

    
    
      struct Unit {};
    

but what about Bottom?

~~~
kbaldor
How about:

class Bottom { private: Bottom(){} };

~~~
Koshkin
This does not look right. If I understand correctly, the position of Bottom in
the hierarchy of types is exactly the opposite to that of Unit: the latter
could serve as the "universal base" (like the type Object), whereas the former
could be seen as the "universal descendant" (some kind of Null type). In other
words, Unit is "anything" and Bottom is "nothing".

~~~
theoh
See
[https://en.wikipedia.org/wiki/Top_type](https://en.wikipedia.org/wiki/Top_type)

------
dkarl
This post does a great job of linking the elements of the mathematical
definition of a monoid with their usefulness in code, helping explain why
monoids are so outstandingly useful in programming. If you've ever wondered
why it's monoids that come up over and over again in programming instead of
another mathematical abstraction, this article will help.

~~~
tw1010
I think "outstandingly useful" is a bit strong and I think it polarizes people
who are on the fence on whether the concept is practically useful or just
formalistic jargon.

~~~
dkarl
Setting aside relevance to common problem domains, I'd say monoids (as monads)
are the most used mathematical abstraction in programming after sets,
functions, induction, total orders, and various forms of graphs. That's pretty
outstanding, especially given their B-list status in mathematics. There are
dozens of explanations of monads on programming blogs and not nearly as many
explanations of, say, rings or models or vector spaces.

------
ShaneWilton
This is a great introduction to monoids. The shape example actually appeared
in a study performed in the early 90s [0]. I'm not convinced that you can draw
too many valuable conclusions from the study, but it's a fun, quick paper to
read.

[0] "haskell vs. ada vs. c++ vs awk vs ... an experiment in software
prototyping productivity" \-
[http://www.cs.yale.edu/publications/techreports/tr1049.pdf](http://www.cs.yale.edu/publications/techreports/tr1049.pdf)

~~~
pavlov
The shape example reminds me of how traditional raytracing renderers work: the
entire scene is a function whose input is [x,y] view space coordinates and
output is [r,g,b] color. To produce an image, you call the function for each
pixel and store the results.

Could be an interesting tutorial to see a raytracer explained in terms of
monoids.

------
mazelife
There's a good blog post as a kind of follow-up to this one that talks about
how thinking in terms of monoids helps enable flat architectures and
composability in Haskell: [http://www.haskellforall.com/2014/04/scalable-
program-archit...](http://www.haskellforall.com/2014/04/scalable-program-
architectures.html)

------
kstrauser
This is awesome. That's the first explanation of the subject that actually
made sense to me, and made me understand why I should care. Thanks for
sharing!

------
fulafel
For Clojurists:

[https://clojuredocs.org/clojure.core.reducers/monoid](https://clojuredocs.org/clojure.core.reducers/monoid)
&
[https://github.com/clojure/clojure/blob/f572a60262852af68cdb...](https://github.com/clojure/clojure/blob/f572a60262852af68cdb561784a517143a5847cf/src/clj/clojure/core/reducers.clj#L320)

For the idea, I think
[https://en.wikibooks.org/wiki/Haskell/Monoids](https://en.wikibooks.org/wiki/Haskell/Monoids)
is better than this post.

------
r41nbowdash
fun fact: you can run shortest path algorithms on pretty much everything as
long as it fulfills the monoid constraints (taking min and combining paths,
operating on distances is a monoid)

so basically, for the cost of implementing two operations you can reuse
dijkstra or bellman-ford to do crazy stuff like belief propagation etc

[http://www.morganclaypool.com/doi/abs/10.2200/S00245ED1V01Y2...](http://www.morganclaypool.com/doi/abs/10.2200/S00245ED1V01Y201001CNT003)

------
goostavos
Could anyone provide a "real world," or generic business coding (database,
input validation, etc, etc..) example that demos rates their usefulness
outside of a pure "mathy" domain.

I find that most of these fp examples tend to focus on simple things like
shapes which tend to already have monoid properties built in. I'd be
interested in seeing examples of how they help your kind of run of the mill
business coding.

------
Vunovati
Coming from an OOP background what made me connect some dots about what the
monoids are and what are they good for after reading the article is that they
can also be viewed as the GOF composite pattern.

I've just stumbled upon an article that describes this:

[http://blog.plasmaconduit.com/the-composite-pattern-and-
mono...](http://blog.plasmaconduit.com/the-composite-pattern-and-monoids/)

------
abritinthebay
Monoids (& monads) are one of those tools that I think help shape your
thinking (like FP) and, even if you don’t use them daily or regularly... still
help make you a better programmer to understand.

The concepts are actually very simple but their _effects_ are complex. This is
great introduction though I think a _little_ high level for beginners.

~~~
umanwizard
Why monoids? Why not groups? Why not vector spaces?

I can't tell why monoids are supposed to be more directly applicable to
programming than any other concept from algebra.

~~~
tikhonj
Intuitively, it's because lots of things we work with in CS don't have a good
notion of inverse. In practice, this usually means you're building up a
structure out of smaller structures: you can always add more to the structure,
but there's nothing you can add to undo what was added previously.

Semirings are interesting for the same reason. "Fun with Semirings"[1] has
some great examples, if you're curious.

[1]:
[https://pdfs.semanticscholar.org/702d/348c32133997e992db362a...](https://pdfs.semanticscholar.org/702d/348c32133997e992db362a19697d5607ab32.pdf)

------
graphememes
monoids taught me that you can use overly complex statements to solve trivial
ideas

------
davexunit
For those that like SICP, the picture language in section 2.2.4 describes a
monoid, though they don't call it that because the term hadn't yet been
adopted. Even so, I found it very helpful in understanding what all the monoid
literature was going on about because I'm much more familiar with Lisp than I
am statically typed ML-family languages.

[http://sarabander.github.io/sicp/html/2_002e2.xhtml#g_t2_002...](http://sarabander.github.io/sicp/html/2_002e2.xhtml#g_t2_002e2_002e4)

~~~
umanwizard
The word "monoid" has been used with its current meaning since the 50s, maybe
before.

I think the authors of SICP didn't describe the picture language as such
because it just isn't a very useful concept, not because they didn't know the
word.

~~~
kazinator
A monoid is just an algebraic group which is missing the concept of the
inverse element.

This has been gutted out of the group so that the category theorists can then
see monoids in situations where they would otherwise have to rack their brains
to come up with the inverse operation.

[https://en.wikipedia.org/wiki/Group_(mathematics)#Definition](https://en.wikipedia.org/wiki/Group_\(mathematics\)#Definition)

For instance, the set of character strings and the catenate operation are
_almost_ a group. The identity element is the empty string.

Closure holds: if a and b are strings, (cat a b) is a string.

Associativity holds : (cat a (cat b c)) is (cat (cat a b) c). (Which is then
just (cat a b c) to a Lisp programmer, (cat a) is a, and (cat) produces the
empty string.)

Identity element: empty string. (cat a "") -> a

Inverse element: oops!

We would have to postulate some sort of "negative string" so that (cat "abc"
-"abc") produces "".

Then we have the problem of what is (cat "abc" -"xyz"): the combination of a
string and the inverse element of a different string.

Let's not bother; just drop this axiom and call it a "monoid".

------
baybal2
I still didn't get it. I need a simpler explanation and examples

~~~
smcl
People are awful at explaining Monad-related concepts. I think everyone starts
with a reasonable explanation and then tweak it to be more succinct until they
end up "a monad is just a monoid in the category of endofunctors"

~~~
umanwizard
By "monad-related concepts" do you just mean abstract algebra? Otherwise, how
are monoids and monads related, other than that they are both algebraic
structures?

~~~
smcl
My comment was pretty poorly written, and is probably better understood in
terms of just "explanations of things starting with mon-" :-D

The concepts aren't tough, people are just pretty bad at putting themselves in
the shoes of a learner, and throw bizarre over-complicated descriptions and
examples into the mix when explaining them. The description I gave is
someone's tongue-in-cheek stab at these which has stuck with me (unless I'm
horrendously off and that is _actually_ someone's legit attempt to describe
monads)

------
ksenzee
> f is associative: for all a, b and c, we have f(f(a, b), c) == f(a, f(b, c))

> Relative paths in a file system form a Monoid under appending

How can appending be associative?

~~~
jhomedall
You might be confusing the associative property with the commutative property
(I do this all the time):

associative: (a + b) + c = a + (b + c)

commutative: a + b = b + a

For example, appending strings is associative, but not commutative. Appending
items to an unordered set is both associative and commutative.

~~~
ksenzee
I was! Thank you.

------
yexponential
> Given a value, we do not have to care how it was built, and whether it is a
> composite or not. We might not be even to tell (*).

missed a word: Able to tell.

~~~
deque-blog
Thank you and good catch :) I corrected it.

------
imtringued
When I tried haskell I wanted to use wreq library to do some simple post and
get requests.

I took a look at docs and found the function definition for a post request.

[https://hackage.haskell.org/package/wreq-0.5.1.0/docs/Networ...](https://hackage.haskell.org/package/wreq-0.5.1.0/docs/Network-
Wreq.html#v:post)

    
    
        post :: Postable a => String -> a -> IO (Response ByteString)
    

We can see that the second parameter should be an instance of the Postable
typeclass.

The examples mention using a JSON value as a parameter

    
    
        >>> r <- post "http://httpbin.org/post" (toJSON [1,2,3])
    

By looking at the definition of toJSON definition we know that toJSON returns
a value

[https://hackage.haskell.org/package/aeson-1.2.1.0/docs/Data-...](https://hackage.haskell.org/package/aeson-1.2.1.0/docs/Data-
Aeson-Types.html#v:toJSON)

Just seeing a single example isn't enough for me to generalise though.

I proceed to go to the definition of the Postable typeclass.

[https://hackage.haskell.org/package/wreq-0.5.1.0/docs/Networ...](https://hackage.haskell.org/package/wreq-0.5.1.0/docs/Network-
Wreq-Types.html#t:Postable)

Unfortunately it doesn't list the instances of the typeclass so I decide to
use hoogle.

[https://www.haskell.org/hoogle/?hoogle=Postable](https://www.haskell.org/hoogle/?hoogle=Postable)

No results found.

I then start looking at the source code of the library until I found this file
which contains the Postable instance for json values.

[https://hackage.haskell.org/package/wreq-0.5.1.0/docs/src/Ne...](https://hackage.haskell.org/package/wreq-0.5.1.0/docs/src/Network-
Wreq-Types.html)

    
    
        import Data.Aeson (Value, encode)
        
        instance Postable Value where
            postPayload = putPayload
    

Why is it so difficult to do a simple task like finding all instances of a
typeclass? In a Java IDE finding the implementations of an interface is just a
single button away and fully automated. Of course I'm assuming that you've
already imported the library that contains the typeclass instance. In this
case the instances are part of the wreq library themselves and not of aeson or
some plugin that you use to connect wreq and aeson. If hoogle worked as I
think it should it could even be superior to a local search that only
considers libraries that are part of your project. I'm a big fan of self
documentation and like the type-aware documentation but this is a case where
although it took a short time I've wasted more time than I'm comfortable with
for a simple program that could be written in python or whatever instead.

I don't care about category theory at all and you can have all the practical
benefits of category theory without putting it on a pedestial. It's neat to
write more generic functions and stuff but there is no need to glorify it.

From a practical standpoint monoid, monad and functor you can think of them as
an interface. When your code accepts a specific implementation like ArrayList
you can in some cases instead use the java interface List to make your code
more generic. When your code accepts a specific implementation like Maybe or
List then sometimes you can use the Monad typeclass to make your code more
generic.

~~~
tikhonj
You can find all the instances of a typeclass by loading all your libraries
into GHCi and then using the :i command:

    
    
        λ> :i Monoid
        class Monoid a where
          mempty :: a
          mappend :: a -> a -> a
          mconcat :: [a] -> a
          {-# MINIMAL mempty, mappend #-}
          	-- Defined in ‘GHC.Base’
        instance [safe] (Monoid a, Monoid b) => Monoid (a :<|> b)
          -- Defined in ‘Servant.API.Alternative’
        instance [safe] Applicative f => Monoid (Traversed a f)
          -- Defined in ‘Control.Lens.Internal.Fold’
        instance [safe] Monad m => Monoid (Sequenced a m)
          -- Defined in ‘Control.Lens.Internal.Fold’
        ... etc ...

~~~
tome
I don't think that will work in this case. After all, that's essentially what
Haddock does to generate its pages. The problem is that the Postable instances
are orphans, for some reason which eludes me.

