That's an interesting article, and it's not entirely wrong, but the
premise is flawed. JQuery is not actually a monad in any reasonable
sense of the term. Let me give a bit of background on monads, but I
will not pretend that anyone is likely to suddenly understand them
just from my explanation. Like a lot of things, especially abstract
things, you have to develop an intuition for them through study and
practice.
Like the article said, Monads come from Category Theory. Some
mathematicians used to call it the 'theory of abstract nonsense' or
something like that (and some of them may still call it that) but it's
really just a continuation of the basic trajectory of mathematics.
Mathematicians can be compared to programmers. For a programmer, the
basic unit of work is a program, by which we'll mean a set of
instructions that encode an algorithm for execution on a computer.
For a mathematician, the basic unit of work is a proof, by which we'll
mean a series of arguments that describe (primarily to other
mathematicians) why some statement about some feature of a
mathematical system must be true.
Mathematicians, it has been said (as has been said of programmers),
are fundamentally lazy, and would like to do as little actual work as
possible to get their results. There are a lot of areas of
mathematical research, and most of them started by someone thinking,
"What would happen if I changed this thing we tend to assume does not
change?" Exploration of these kinds of ideas can open new fields of
mathematics, and eventually physics and engineering. But the result is
that there's a lot of stuff in common between different fields of
mathematics. So, in the interest of laziness (or economy, if you want
to be nice) mathematicians have been looking for ways to prove things
about whole groups of mathematical systems based on the properties
that they have in common. When you prove something in a framework
like that, you can use the proof in any new (or established) field of
mathematics just by showing that your field adheres to the properties
that were assumed by your proof.
This process has led (over hundreds of years) to increasingly abstract
ways of looking at mathematics and proof. If you start with basic
counting and arithmetic, you can abstract over that by forming
algebra, in which you can replace concrete numbers with abstract
variables and show that equations hold for whole patterns of
mathematical expressions. If you look at the concept of a number, it
turns out that it can refer to several differen things of increasing
complexity: the positive integers, the natural numbers, the rational
numbers, the real numbers, the complex numbers, etc. It turns out
that we can refer to all of these distinct things as simply 'numbers'
because they all obey the same set of arithmetic properties. This
form of abstraction developed into set theory, group theory, etc.
Category theory is sort of the next step in the abstraction ladder.
The idea is to do proofs in a very abstract domain that show how
potentially very different fields of mathematics can map to one
another, so that proofs in this abstract domain can apply to huge
areas of mathematics. Because it's so abstract and removed from
everyday arithmetic, there's no common vocabulary for describing these
abstract objects. Their value to mathematics is in the fact that they
are so abstract, so attempting to explain them in more concrete terms
is necessarliy a weakening of what they are. Like any specialized
field, the vocabulary is unique and it takes time to develop a feel
for what the terms mean. I'm still not all that great at it, so I
won't attempt to dive into a deep explanation.
Computer scientists and programmers do a similar thing with programs.
You can create languages that abstract over different properties of
programs. I think you're all somewhat familiar with this idea, so I
won't get into it too deeply, but you can probably see a bit of a
correspondence between this method of forming abstractions and the
method of forming abstractions that mathematicians use. It turns out
that when you are a computer scientist studying programming languages,
it's helpful to be a bit of a mathematician as well, because
mathematics is very useful for describing the properties of things and
providing a context for proving things about them.
Anyway, a programming language can be described in terms of three
basic families of characteristics: syntax, which is the form of the
langauge, or set of symbols and their combinations that make valid
statements in the language; semantics, which is how you can tell what
the valid statements of the languages *mean*; and pragmatics, which
includes all the messy details about the mapping between the meaning
of the language and the machine it's going to run on. Of all these,
the semantic family of characteristics are most interesting to
langauge researchers, because these contain the real power of the
language to carry meaning. So, if you want to say something very
precisely about the meanings of programs in your language, you need to
formally define the semantics of the language, and by "formally
define" I mean capture the meaning of the language in some sort of
system of symbols that can be mechanically manipulated (by human or
computer) to deduce properties of the program.
There are a number of ways to do this, but the primary ones are
operational semantics, denotational semantics, and axiomatic
semantics. They are by no means exclusive; it can be useful to define
some features of the language via one semantic model and some in
another, or to apply different models to the same features in order to
explore different properties of the features. Operational semantics
basically describe the what the language means with respect to some
sort of an "abstract machine" and the way the language maps onto
operations in that machine, or sometimes by direct syntactic
manipulation and rewriting of the language according to a set of
transformation rules. Denotational semantics maps statements in the
language into some sort of direct mathematical statement, generally in
a specific field of mathematics such as a flavor of set theory, type
theory, or domain theory. Axiomatic semantics say that a statement in
the language means precisely what can be logically proved about it.
Anyway, computer scientists have been working on the formal semantics
of programming languages for about as long as programming languages
have existed, which means that they've had to map languages like
Fortran directly to mathematical statements or operations on a
mathematically-defined abstract machine. Although statements in
Fortran look a lot like mathematics and share a lot of similarities,
the fact that variables can be assigned to is a foreign concept to
mathematics and has to be mapped to something else, which is generally
called the 'store'. I won't get into all the details, but the general
idea is that statements are mapped into their semantic definition as
operations that occur in sequence and which take the current state of
the store as an input, returning a modified store as an output.
Anyway, this had been the standard way of doing things for a while,
and all the management of the store and the way that statements
interacted with it had to be carried around in the way you described
the operational semantics. This was a bit awkward, and eventually a
guy named Eugenio Moggi discovered that the Category theorists had
come up with an abstract bit of mathematical structure that was a very
close fit for the work you need to do in programming language
semantics of stateful languages. He showed in a paper how you could
use a categorical thing called a Monad to represent the state of a
program, and the structure of the Monad could be made to describe the
sequencing of statements and modification of state from statement to
statement. This let you apply all the ways of manipulating
categorical structures that the category theorists had been working on
to the proofs you were trying to make in your semantics as well as
giving a clearer notation for describing things. This technique
eventually got adopted on a wider scale into the CS field of
operational semantics.
Some time later, programming language researchers who were working on
purely functional programming languages decided that it would be in
their best interest to take all the many languages that they'd been
working with as the field developed and combine what they'd learned
from them into a single language that would be a sort of 'lingua
franca' for functional programming research. This had been done
previously with languages like Algol, and to a lesser extent Scheme,
but new developments in the mathematics of programming language theory
demanded a language that played to the strengths of those
developments. So, Haskell was born as a research collaboration
language. It didn't have to worry much about pragmatics like how to
do I/O, because the primary purpose of the language was to examine and
develop the semantics. But eventually people wanted to do real
programming with it, partially to validate all the work they'd been
doing on developing a sophisitcated language. What use is a
sophisticated language if you can't make any flashy programs with it?
So Haskell developed a few different ways of doing I/O that were
mostly rather awkward and embarrasing, though you can actually find
research papers describing how cool they were.
Anyway, at some point Simon Peyton Jones, an employee of Microsoft
Research and one of the driving forces behind the development of
Haskell, realized that Moggi's work on describing the operational
semantics of programming languages via Monads could be implemented
pretty directly in Haskell, thanks to the fact that the meaning of
Haskell programs maps fairly cleanly to mathematical statements, and
vice versa. So he could write the operational semantics for an
embedded DSL describing the meaning of I/O operations directly in
Haskell, making the Haskell implementation the abstract machine. This
let him take advantage of the notational clarity Moggi had developed
to make a pretty clear description of the I/O operations and their
sequencing in a Haskell program. Although this was a big improvement
by itself, he realized that he could take one more step and make a bit
of syntactic sugar that mapped the Monadic expressions back to
statements in a simple concrete statement-based language. This gave a
very friendly way to write I/O operations in Haskell.
This was very cool in itself, but the fact that it was done via the
mapping capabilities of operational semantics and category theory
meant that he hadn't just introduced an I/O system; he'd introduced an
abstract DSL syntax that could have its operational semantics
reprogrammed within Haskell! The I/O Monad defined one meaning for the
basic operations, but because of the way the Type Class mechanism
works in Haskell, you could provide an entirely different set of
operations for your own Monad type (Monad itself is a Type Class, not
a single type) providing they met the required interface and followed
the Monad Laws (which let you use the category theory theorems to
reason about how the operations combine with other structures in
category theory, and are what make them actually a Monad instead of
just some ad-hoc collection of operations). Once you define a new
Monad, the way in which a do expression is interpreted depends on the
operational semantics you defined with that Monad.
I hope you can see that while this is a pretty abstract thing and a
bit difficult to take in all at once, it's a very powerful thing to
have in a language. It basically changed the course of Haskell
development for the next decade or so as people delved into Monads and
category theory and discovered how many basic types in Haskell could
be mapped into Monads and thus gain access to the 'do' syntax and all
the mechanisms and logic that had been built up around the Monad Type
Class. It turns out that Monads are a fairly specialized form of
structure in category theory, and more abstract structures could be
expressed in Haskell as well. When you wrote programs in terms of
these abstract structures, you could re-use the same implementations
of operations whenever a type you defined happened to map cleanly to
one of the structures. And, just like the way that natural numbers
and real numbers both adhere to the same kinds of rules for combining
things arithmetically, it turns out that many structures in programs
adhere to some basic kinds of rules for combining things. A lot of
these groups of rules for operating on things have been collected and
given funny names, and they can help you organize programs and take
advantage of work that's already been done in defining how those rules
for operating on things have been implemented.
By now, I will be surprised if anyone is still reading, but if you
have got this far I hope that you see a bit of the idea behind the
motivation for all the weirdly named bits in Haskell, and how they're
really general concepts that actually show up all the time in
languages, since they were originally developed in the context of
computer science to describe how normal stateful procedural languages
work! If anyone has specific questions or would like pointers for
further avenues of study, let me know and I'll be happy to try to
provide answers or references.
--Levi
On Thu, May 2, 2013 at 8:30 AM, justin <[email protected]> wrote:
> This is probably the most useful article on monads I've seen:
>
> http://importantshock.wordpress.com/2009/01/18/jquery-is-a-monad/
>
> --j
>
>
> On Thu, May 2, 2013 at 7:06 AM, justin <[email protected]> wrote:
>
>> A monad is a monoid in the category of endofunctors, what's the problem?
>>
>>
>> On Thu, May 2, 2013 at 5:36 AM, S. Dale Morrey <[email protected]>wrote:
>>
>>> I just read that Java 8 will include Monads. I tried to google the term
>>> and came up with mind blowing complex stuff which may have stripped a gear
>>> in my brain.
>>>
>>> Can someone please explain in terms so simple a Java programmer can
>>> explain, what the heck is a monad or more importantly what would be a
>>> valid
>>> use case for one? In fact I'm not sure what they are is as important as
>>> why, when or how I would use one (or several) since of course I tend to
>>> learn by example.
>>>
>>> If there is anything similar in Perl, PHP or Python, those examples would
>>> be helpful too.
>>> Car analogies appreciated as well.
>>>
>>> Thanks!
>>>
>>> /*
>>> PLUG: http://plug.org, #utah on irc.freenode.net
>>> Unsubscribe: http://plug.org/mailman/options/plug
>>> Don't fear the penguin.
>>> */
>>>
>>
>>
>>
>> --
>> http://justinhileman.com
>>
>
>
>
> --
> http://justinhileman.com
>
> /*
> PLUG: http://plug.org, #utah on irc.freenode.net
> Unsubscribe: http://plug.org/mailman/options/plug
> Don't fear the penguin.
> */
/*
PLUG: http://plug.org, #utah on irc.freenode.net
Unsubscribe: http://plug.org/mailman/options/plug
Don't fear the penguin.
*/