
A Haskell Journey - prakash
http://pindancing.blogspot.com/2010/02/haskell-journey.html
======
jrockway
_What we really need is an "Advanced Haskell" book which assumes a knowledge
of Level 1 Haskell and then lays out the CT bits in an orderly fashion. Monads
for example, are best understood from a Category Theory perspective than
through some tortured analogy to Space Stations or Elephants or whatever._

I think people are looking for something profound where there really isn't
anything as profound as they are imagining. Monads are applicative functors
with "join". Applicative functors are functors with "ap". Functors are
containers that can apply a function ("fmap") to their contents. Add in some
laws, and that's what you have; a few very generic concepts that let similar
things have the same API. There is nothing more profound here than any other
generic API, except that the "genericness" goes beyond what most programmers
are used to. (Most programmers seem to be used to abstractions that take some
"noun" and make variants -- map => hashmap, alist, plist, binary tree; list =>
linked list, vector. Haskell's abstraction is more like an adjective -- a
functor isn't really a thing that you can hold in your hand, it's just a
property of something. "Monad" is a property of "list" like "red" is a
property of "apple".)

(Monoids are even more generic -- they are something that has an "identity"
and an "append" operation. Lists are monoids, but so are booleans like "Any"
and "All", and integers form monoids over addition and multiplication. Monoid
is just a word that relates the common properties. The advantage of this
abstraction in Haskell is that you can "mconcat" a list of sentences into a
paragraph just like you can "mconcat" a list of numbers into their sum.)

Monads get a lot of mindshare in Haskell because they are a good way to
sequence computations -- you write a single sequencing combinator, and you get
convenient syntax sugar and a big collection of utility functions ("liftM",
etc.). Write another function, and you can create monads from other monads,
which happens to be convenient for writing applications. (Reading the
definition of the type "X" in xmonad is enlightening, if only because you
realize that the entire program is a bunch of functions that return "X", and
that the mechanics of X's "monad" instance make the program work the way it
does. xmonad is really the X monad!)

Arrows are like monads, except instead of "bind" you have a variety of other
combinators; "fanin", "fanout", etc. If your data flow looks like that, Arrows
make your code look like your dataflow. (And from a category theoretic
perspective, every monad is an arrow. Kind of how every "light red" is "red".)

I think RWH provides good coverage of monads, although reading RWH once you
"get" monads can be tedious. The good news is, by the time you learn what the
word "monad" means, you already know what it does for you.

So anyway, just start programming, and you'll see why these abstractions are
useful. You'll also see why "easy to understand" abstractions like "foldable"
and "traversable" are useful too, even though there is not much category
theory there.

I guess to summarize: don't let unfamiliar words scare you away from simple
concepts! You already know how to program, and programming Haskell is just
programming!

~~~
camccann
_Functors are containers that can apply a function ("fmap") to their contents.
(...) Monoids are even more generic -- they are something that has an
"identity" and an "append" operation._

Argh! Pet peeve time. Functors are not containers and calling them that makes
it harder to understand how something like IO, ((->) a), or a Parsec parser
qualify; also, some container types aren't (and can't be) Functors because
they aren't polymorphic in the contained type (IntSet or ByteString, for
instance).

Likewise, calling the Monoid operation "append" is needlessly confusing (and
yes, the names the standard library uses are terrible). It's an associative
binary operation with an identity value and no semantics whatsoever beyond
that. Appending data structures is likely to form a monoid, but so can merging
them (union and intersection both work). Any instance of Ord forms monoids
under min and max. Functions are a monoid under composition. Even () forms a
(trivial) monoid.

I'm pretty sure none of that is news to you, but I think using descriptions
like "container" and "append" invoke too many preconceived ideas for people
new to Haskell and creates barriers to understanding more than it helps. Most
of this stuff is actually quite simple, but it's almost painfully abstract,
and using concrete metaphors of familiar things obscures the full generality.

It's particularly a problem with Monoid, because the concept is both utterly
trivial and broadly useful, but calling it "append" leads to people
complaining about Haskell using a needlessly cryptic term for "appendable
things" while simultaneously missing the entire point of the type class.

 _So anyway, just start programming, and you'll see why these abstractions are
useful. You'll also see why "easy to understand" abstractions like "foldable"
and "traversable" are useful too, even though there is not much category
theory there._

For what it's worth, from a mathy perspective, I think Traversable represents
some sort of distributive law between Functors (e.g., lets you do something
that looks like "f (g a) -> g (f a)").

In categorical terms Foldable is related to "catamorphisms", though to my
understanding the relevant bits of category theory were first explored by, and
remain of interest mostly to, programming language theorists. Look at
<http://knol.google.com/k/edward-kmett/catamorphisms> if you're brave
enough...

~~~
jrockway
You're right that calling a functor a container is an oversimplification. But
when you start explaining something at full generality, it only makes sense to
people that already understand the full generality. Once you understand how
List and Tree are similar, you can understand how List, Tree, Reader, and IO
are similar. But if you don't see any connections between List and Tree, you
are never going to see any connection between List and IO. So, you need to
simplify, understand the simplification, and then try to attack full
generality.

The same goes for monoids. Many people won't see any use for "identity +
associative binary operator". But they will understand the similarities
between "append to a list" and "add numbers". Once you see something concrete,
then you can worry about abstraction. If you don't understand the concrete,
though, you aren't going to get there from the abstraction.

(Nobody ever said, "I'll define a functor to be ... Now I'll write a program
with this functor!" Instead, they noticed how lists and trees were similar,
and invented the functor abstraction afterwards. If you learn and discover
things the same way they did, you'll eventually have the same deep
understanding they do. That understanding is what allows you to use the
abstractions, not the definition you find in a textbook.)

So anyway, if you are teaching people Haskell, it's better to teach them the
concrete. Once they understand that, you can amend the definition to be fully
abstract. Then they will be comfortable with the abstraction and its
applications.

------
jriddycuz
I think what we need is "Real World Category Theory" to go along with "Real
World Haskell." It's not surprising that it's difficult to get your head
around concepts lovingly referred to as "abstract nonsense." The reality is,
of course, that CT is really useful because it is so general, but that same
generality is what makes it really hard to grok.

More experienced Haskell-ers are often very quick to offer encouragement and
to tell you that Monads and Monoids and Functors and Arrows/Morphisms aren't
that tough, and they're right, but in some ways they are missing the point.
The level of abstraction that those concepts exist is so foreign to most
people that they have trouble conceiving of it in any meaningful way until
they actually go through and learn enough to kinda get it. At least Monads and
Monoids have kinda scary names. Basic category theory concepts like arrows and
objects have familiar, inviting name, but they refer to something totally
different. Worse than being scared by words, these words leave us thinking we
know things they don't.

------
plinkplonk
I don't think this is HN material (I wrote the blog post,I didn't submit it).
This post is just me "thinking by writing", trying to clear my head.

I thought it was a largely content free post, just some rambling, and yet here
it is on HN. Slow news day I imagine! :-P.

Here is a summary, to save you time - Haskell needs a book (to complement RWH)
focusing on the the Category Theory aspects.

~~~
jrockway
The advantage of HN is that you get better comments than you would directly on
your blog. Feedback++.

~~~
plinkplonk
"The advantage of HN is that you get better comments than you would directly
on your blog. Feedback++."

Oh I agree. HN has the quality of having awesome comments and discussion on
very bland subject material.

I am just faintly embarassed that something that was just me rambling in prose
landed up here.

