

The category design pattern - profquail
http://www.haskellforall.com/2012/08/the-category-design-pattern.html

======
ggchappell
Leaving aside the category stuff for a moment, I think the first couple of
paragraphs of this article make an excellent point.

> Functional programming is all the rage these days, but in this post I want
> to emphasize that functional programming is a subset of a more important
> overarching programming paradigm: compositional programming.

Indeed. So there is another article just begging to be written: "Introduction
to Compositional Programming". I've seen any number of articles that say
something like, "I especially like these because they are composable." But
I've seen very little on figuring out how to solve problems by using
composable components, or so that the solution itself is composable.

Another thought: we really should be giving more thought to composition when
designing programming-language syntax and features. Haskell excels at writing
composable components; it also has nice syntax for composing them. Both are
much less natural in "C". Various replacements for "C" are being proposed; is
thought being given to composability in them? Similarly, the popularity of
Python's generators is largely because they allow for the easy design of
composable components. Etc.

~~~
tikhonj
The point of this article is that you _don't_ want to leave the category stuff
aside. A category is essentially a well-defined and systematic way to reason
about--and program with--composition. An introduction to programming with
categories would, by its very nature, have to be an introduction to
programming compositionally.

Moreover, I think a introduction using terms and ideas from category theory
would be more useful, more thorough and more enlightening than an introduction
to "compositional programming" without any math. It provides a nice structure
and enables you to consider composition more abstractly, which lets you use
compositional programming in more places.

~~~
davidcuddeback
_> Moreover, I think a introduction using terms and ideas from category theory
would be more useful, more thorough and more enlightening than an introduction
to "compositional programming" without any math._

Yeah, this article left me wanting to know more about category theory. But
that in itself is valuable. I googled and found a couple introductory papers
[1,2], some slides introducing category theory for software engineers [3]
(with a NSFW diagram on page 8), and an introduction to category theory as it
applies to Haskell [4].

[1]: <http://wwwhome.cs.utwente.nl/~fokkinga/mmf92b.html>

[2]: (PDF)
[http://www.staff.science.uu.nl/~ooste110/syllabi/catsmoeder....](http://www.staff.science.uu.nl/~ooste110/syllabi/catsmoeder.pdf)

[3]: (PDF) <http://www.cs.toronto.edu/~sme/presentations/cat101.pdf>

[4]: <http://en.wikibooks.org/wiki/Haskell/Category_theory>

------
freyrs3
On an aside if you haven't checked out Gabriel's ``pipes`` library, its
definitely worth a read. It's some of the most elegant Haskell I've had the
pleasure of reading.

[http://hackage.haskell.org/packages/archive/pipes/2.2.0/doc/...](http://hackage.haskell.org/packages/archive/pipes/2.2.0/doc/html/Control-
Pipe.html)

------
skybrian
This is a nice explanation about how category theory relates to programming,
but it doesn't explain how mathematical rigor helps us in this area. Making a
rough analogy with function composition and unix pipes seems sufficient to get
the point across to most programmers. I suppose you could actually write
generic code that works with more than one category but that seems like
unnecessary and unhelpful abstraction, compared to just writing the code twice
in more concrete terms.

~~~
tikhonj
There are several advantages to writing code at that level of abstraction.

It's a great way to encourage code reuse, even in fairly disparate domains.
Haskell has some of the most versatile libraries of any language I've used by
using mathematical abstractions like this. As a concrete example, there are
functions like foldM which is like a normal fold except it can handle errors,
state, nondeterminism or even parsing!

The abstractions are well-understood, which makes it easier to reason about.
You get a bunch of theorems and conclusions for free just by formulating your
program in mathematical terms. You can then easily take advantage of these to
simplify, verify or optimize your code. For example, if you know that your
data type forms a valid functor, you can always rewrite fmap a . fmap b as
fmap (a . b), turning two passes into one! If you wrote a map-like function
separately for each different type, taking advantage of this pattern would be
more difficult.

You are also restricted in what you can do--any code that is generic across
all categories can _only_ use composition. This leaves you less room to make
mistakes. If you write a function just for strings, you can accidentally add
characters or always return an empty string or any number of string-specific
behaviors. If you write a function against some abstraction like a functor,
you cannot make any of those mistakes--there is simply no way to formulate
them for all functors.

These abstractions are just a reification of a common pattern across a bunch
of domains. Making the pattern explicit makes it easier to see and use and
makes your code simpler.

~~~
skybrian
This sounds promising, but it's far too abstract to be convincing. Can you
give a example of a useful program where you need to do any of these things?

~~~
freyrs3
Sure, look at most Haskell libraries. A lot of them expose some of their APIs
as monads, arrows, functors, and kleisli categories.

Some good examples: hakyll, Pandoc, pipes, conduits, warp, scotty, or anything
by Edward Kmett ( <https://github.com/ekmett/> )

~~~
skybrian
Thanks, but that's far too much to take in at once. How about just one simple
example?

I did skim through them, so to be specific: hakyll, Pandoc, warp, and scotty
are what I'd call practical programs, though they approximate more popular
programs written in other languages, so there's the question of why someone
who wasn't already a Haskell programmer should choose them. Pipes, conduits,
and most of the stuff by Kmett appear to be libraries implementing other
abstractions that themselves would have be justified by use in a practical
program.

~~~
freyrs3
> Pipes, conduits, and most of the stuff by Kmett appear to be libraries
> implementing other abstractions that themselves would have be justified by
> use in a practical program.

I'm not sure I understand what you mean by "practical programming".

This may just be a cultural difference but one of the big ideas of Haskell is
using a library whose "core calculus" is provably correct and then combining
them in ways that preserve that correctness. So I would argue that the
justification of the libraries is not in the practical ( if I understand your
usage of the word?) usage but in the thoroughness and compositional semantics
that they provide. That's where the category theory inspired patterns (
zippers, monads, arrows, etc ) become important.

~~~
skybrian
Okay, let's define "practical programming" as creating programs that will be
of use to someone who doesn't know the programming language that the program
was written in. So in this case, this means writing Haskell programs that will
be used by people who don't know Haskell.

This isn't the only reason to write a program of course. You can do it just
for fun or to explore the mathematics. But I'm mostly interested in
abstractions that might be useful for solving problems outside mathematics.

~~~
freyrs3
None of the libraries or patterns I mentioned above are designed for the
purpose of exploring category theory. Though some people do do that, but they
tend to live in their own world.

A lot of Haskellers just happen to exploit bits of CT it because its a great
framework for writing and reasoning about code. Some people do use Haskell as
a way to explore category theory but for example Tekmo isn't writing pipes as
a means to explore the theory of free monads, they've been well studied since
the 80s. I believe he just happens to find that they are an excellent way of
chaining together bits of control flow.

At that heart of the problem he's tackling is very practical problem that's
tied to data flow and resource management. For example, I've written a library
against pipes which handles resource management of ZeroMQ sockets for a large
distributed system and find that my code under pipes is much more manageable.

~~~
skybrian
Okay, sure, resource management is what I'd call a practical problem, and
pipelines are familiar from Unix (and Go). It looks like this pipe library has
a nice practical example: enforcing the category laws means that it handles
terminating pipelines consistently:

[http://hackage.haskell.org/packages/archive/pipes/1.0.1/doc/...](http://hackage.haskell.org/packages/archive/pipes/1.0.1/doc/html/Control-
Pipe.html)

------
gtani
related

[http://golem.ph.utexas.edu/category/2012/06/the_gamification...](http://golem.ph.utexas.edu/category/2012/06/the_gamification_of_higher_cat.html)

[http://golem.ph.utexas.edu/category/2012/08/categorical_unif...](http://golem.ph.utexas.edu/category/2012/08/categorical_unification.html)

<http://math.ucr.edu/home/baez/rosetta.pdf>

