

Monads in C++ - VeXocide
http://bartoszmilewski.wordpress.com/2011/07/11/monads-in-c/

======
Peaker
People confuse special-cases (Monad instances) with Monads (the abstraction).

"Monads in C++" would be an encoding of the return/bind interface, which is
possible (surprisingly, at least to me), and then writing a library of
combinators that work with this interface and _any_ instance of them.

What this article (and countless others) are about is a particular encoding of
bind/return for a single type, and not the Monad abstraction in general.

------
bandushrew
This is fantastic.

The idea that C++ meta programming is most easily understood as an
(unnecessary complicated) functional language actually makes a huge amount of
sense to me, and I particularly enjoy the lovely sense of balance it invokes.

------
VeXocide
His three-hour BoostCon presentation can be found at
[http://blip.tv/boostcon/haskell-the-pseudocode-language-
for-...](http://blip.tv/boostcon/haskell-the-pseudocode-language-for-c-
template-metaprogramming-5258033) (mirrored at
[http://wipkip.nikhef.nl/events/BoostCon/2011/Boostcon-
Haskel...](http://wipkip.nikhef.nl/events/BoostCon/2011/Boostcon-
HaskellThePseudocodeLanguageForCTemplateMetaprogramming927.mp4))

~~~
BartoszMilewski
Here's a better link with three videos and slides:
[http://www.corensic.com/Community/Resources/BoostconVideo.as...](http://www.corensic.com/Community/Resources/BoostconVideo.aspx)

------
swah
How long did it take you guys to read this post?

~~~
palish
About fifteen seconds. Skimmed it, realized it was "another instance of
someone attempting to do yet-another-bad-thing-in-C++", then closed it.

I went through the same phase in my C++ career. (Mine was attempting to add
FOREACH to my projects without depending on Boost.) I think at some point
every C++ dev gets tired of writing boilerplate code, and then spends the next
few days implementing something that would've otherwise taken them a few
hours.

Once you accept that C++ is _not_ Lisp, and doesn't need to be, then you
become much more productive.

Additionally, your resulting C++ code is much more likely to _actually be used
by other C++ engineers_.

Lastly, these sorts of libraries tend to be very difficult to debug unless you
were the one who wrote it.

~~~
pvarangot
It's in fact an attempt to explain how the author got to understand the inner
workings of Boost's Proto library, which is already available for C++ and
pretty much a successful project as far as it goes. For people also into
Haskell, it's a very concise and insightful attempt indeed.

I understand your rant, but I'm not sure this is the place to go and spew
it... Actually some people enjoy studying programming languages themselves and
sometimes come up with useful stuff for engineers that like building more
concrete stuff.

~~~
psykotic
When I see someone towards the middle of their career who is still in the
thrall of C++ metaprogramming, it excites in me a mixture of genuine sympathy
and condescending pity (and if they're a coworker of mine, righteous wrath). I
am glad I went through that phase in my late teens and had the nonsense shook
out of me by my first professional experience as a programmer.

It's fine to pursue this as fun for its own sake if you are under no pretense
as to its practical utility. But the danger of having your fun it in a bread-
and-butter language like C++ is that you will be tempted to let it infect your
workaday coding style. That's one of the perpetual dangers of hiring bright,
overeager C++ programmers at the junior level.

Boost is a minefield. Its less booby-trapped libraries have made it into the
next C++ standard library, but the more hardcore indulgences in
metaprogramming like Spirit deserve all the scorn that is customarily heaped
on them, if not more.

~~~
wolfgangK
Your post is very condescending but also very light on facts. To someone
successfully using C++ metaprogramming you just sound like you failed to find
how and when to use it. (I do agree that it can get ugly wrt error messages
and syntax as neither the compilers nor the language were designed with
metaprogramming in mind.)

~~~
psykotic
The condescension was very much intended. Look, I'm not going to convince
anyone of this point of view with a few hastily typed-out paragraphs on Hacker
News. No-one can do that. It's something that rings true or false depending on
your experience. My experience is that most uses of C++'s features beyond the
rudimentary lead to software that takes forever to build, forever to run and
forever to maintain, all of which are unacceptable and inexcucable. I started
out in my pre-career as an enthusiastic C++ supporter who knew most of the
tricks and dark corners of the language; template metaprogramming was (and
still is) easy as pie for me. But every experience I've had since then has
pushed me in the opposite direction, away from immature self-indulgent
cleverness. Nowadays I mostly use C or a very C-like subset of C++.

------
Miky
This is the worst example of cargo cult programming I've seen in a good while.

~~~
Miky
OK, downvotes. Why, exactly? I'm not trying to troll. Monads as commonly
explained on blog posts are cargo cult mathematics, and monads used in
languages like C++ where they make code longer and more complicated instead of
simpler, are cargo cult programming. I thought comments were for discussion,
not silencing anything negative.

~~~
nandemo
Dismissing a well-written and elaborate post in a one-liner with no convincing
arguments is usually considered bad form.

 _Cargo cult programming_ itself seems to be an overused term. According to
wikipedia it means "a style of computer programming that is characterized by
the ritual inclusion of code or program structures that serve no real purpose.
Cargo cult programming is typically symptomatic of a programmer not
understanding either a bug he or she was attempting to solve or the apparent
solution". I've seen this done. I knew programmers who would call the same
(side-effecting) function twice in a row, "just in case, since it might fail
the first time", instead of actually checking the function's return code etc.

Do you really think the post's author has no idea of what is talking about?
That he copy-pasted some code and ended up with an EDSL in C++? The particular
code he shows might not be practical, but that doesn't mean it's "cargo cult".
For instance, perl-golf, obfuscated C contests and implementing X in
Javascript aren't practical-minded activities either, but you can't call it
"cargo cult": programmers engaging in them aren't exactly clueless.

Again, monads may be perceived as "hyped" but that doesn't mean they're "cargo
cult mathematics" any more than the Y combinator is.

~~~
Miky
I guess we're using the term “cargo cult programming” about different things.
I'm not arguing that the author of this post doesn't have a very good
knowledge of C++, and a somewhat good knowledge of how monads are sometimes
used in Haskell. The problem is that the way monads are sometimes used in
Haskell is cargo cult mathematics (I'll explain in a moment), and the way he
implements monads in C++ gains absolutely none of the benefits yielded by
their use in Haskell, adding only useless complexity to his code. While this
isn't an example of the incompetence you have witnessed, it is an example of
ritual inclusion of program structures that do not yield any benefits.

Monads are an example of using patterns from category theory in programming.
This can be done nicely in languages with the facilities to do so, like
Haskell. For instance, Functors, Monoids, and Comonads are patterns that are
sometimes used in Haskell that are taken from category theory. However, the
way monads are often used in Haskell is cargo cult mathematics. Here's why.

In category theory, monads are defined as functors with two associated natural
transformations. However, in Haskell, the typeclass Monad is not even defined
as a subclass of Functor. Additionally, one of the two natural transformations
is swapped out for another (join is replaced by bind), and both are
misleadingly renamed (return and bind don't suggest their actual meanings).
Also, monads are often overkill for the problems they are applied to. Rather
than think carefully about which pattern to apply to the problem, programmers
echo the trumpeted “Monads are the fundamental method of abstraction!” and use
them in their code, for that is the right thing to do.

Monads are not actions. Monads are not defined as a way to thread state
through code. The type IO a in Haskell is an action, and since the interface
provided to this abstract data type is monadic, there is a great deal of
confusion about what the properties of a monad are and what the properties of
the IO a type are. This blog post confuses them.

Even though monads are misused in this way in Haskell, their use still brings
benefits. This is because Haskell gives the programmer facilities to write
code that works over every monad. However, this is not the case in this blog
post. The code in this blog post is parametrized over the types returned by
the actions, but not over the actual type of action. One can see where he is
looking at Haskell implementations of the functions to translate into C++ that
they aren't. This basically renders the monads useless.

Another telling example of how these aren't really monads is when he says “You
might have noticed that I use the words “action” and “program”
interchangeably, although, strictly speaking, an action is the contents of a
program. However, this distinction is an artifact or a Haskell quirk — a monad
can’t be defined using a type alias, so we need the Prog type to encapsulate
the action. Curiously, we won’t have this problem in C++.” In Haskell, an
instance of Monad needs to be a container type, because the two functions that
are the fundamental definition of a monad operate on nested containers (unit
puts anything into a container, and join makes a container of containers into
a single container). Since his C++ code isn't doing anything like this, he
hasn't made a monad at all. He's simply made an extra layer of complexity in
compiling an AST into actual code at compile-time, a task which has nothing to
do with the nature of a monad. I'd reckon one could write code for compile-
time EDSL's in C++ using no monads at all that would be much cleaner.

Sure, you can make a structure and slap the label monad on it and use return
and bind functions (which aren't really what a monad fundamentally is) to put
together your code, but if you can't write code that works as well on that
monad as on other monads without changes, you've accomplished nothing but
useless complexity. In other words, including program structures because they
are accepted as good rather than because they have any benefit.

~~~
BartoszMilewski
@miky: I responded to (the copy of) this comment on reddit:
[http://www.reddit.com/r/programming/comments/in84h/monads_in...](http://www.reddit.com/r/programming/comments/in84h/monads_in_c/)
.

