Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Monad: if you have a data structure that wraps some value of any type, then you also have to implement the interface that provides `return` and `bind`

So it's a wrapper that implements a particular interface? Then why, oh why, do we have so many people who spout, "A monad is just a monoid in the category of endofunctors, what's the problem?" Gilad Bracha covered this in a talk once.

Because of the way the rules of the Monad interface are structured you're guaranteed that the functions you use to compose your Monads together will be executed in sequence with respect to their definition in your function body.

So it's a way of imperatively declaring execution sequence dependencies that lets you reason as if there's only pure functions most of the time. This seems to be the case for all functional programming languages/environments. When you get down to it, they're all, in the words of Garrison Keillor, "Pure, mostly."



'So it's a wrapper that implements a particular interface? Then why, oh why, do we have so many people who spout, "A monad is just a monoid in the category of endofunctors, what's the problem?"'

"Monad" seems to be just beyond the complexity event horizon where it is difficult for people to get a really clean idea of what it is, so instead we've got dozens of ideas of what they are floating around, probably a good two-thirds of them with fundamental errors in them, which then contributes to the general haze surrounding the ideas.

I've got a mostly-written blog post on deck with the tentative title "Functors and Monads For People Who Have Read Too Many Tutorials", for which around 80% of it isn't explaining what they are, but systematically walking through all the errors I've seen (some of which are in the type notation for Haskell itself; the "[a]" abbreviation for what should be "[] a", if not "List a", alone has done untold damage to comprehension) before finally getting down to what the things are.

(Functor in particular is so trivial it's hard to believe it's that trivial when you finally really get it. Monad legitimately has a bit of a twist in it, and some of the specific uses of that interface take that twist and hammer it home to produce some very funky code, so the fact that it's a bit foggy isn't that big a surprise. The fog that functor has picked up by association with monad is much, much larger than the concept itself, though.)

"So it's a way of imperatively declaring execution sequence dependencies that lets you reason as if there's only pure functions most of the time."

It turns out no, that's just one use of them. A very big one, a very natural one, and the one that drove their prominence in the current debate... but it's not actually what the interface is "about" per se. For a good counterexample, consider the parsing monad implementations that "declaratively" [1] create a parser. It's not really about declaring execution sequences.

(There's also a non-trivial amount of confusion that arises from the fact that monad and laziness have a lot of interaction. The monad interface in a strict language would be used differently than it can be in Haskell.)


Functor, Monoid, and Semigroup are the worst. There's a complete lack of literacy when it comes to abstract algebra in practical programming. Monoid is so incredibly simple but the jargon and terminology is what makes them scary to newcomers.

Monoid: A data structure wrapping a value of some type that implements the Monoid interface. The interface has two methods: `identity` and `append`. If you implement those methods for your structure and your implementation follows particular rules then... you have a Monoid.

Why are they cool? You can append a lot of things together; not just lists. You now have a generic, binary append operator `mappend` that can join together anything that implements the Monoid interface.

What can you use it for? Well.. lists for a start. Configuration? Sure! Load up configs from the shell environment, the `~/.myapp` file, and the `/etc/myapp` file; concatenate them together with your generic `mappend`... boom. Streams? Sure. Trees? Why not. If you can implement the interface you get the operators. You code can stop caring whether it's a this or that. It can focus more on do this, do that.

Semigroup: a monoid without the `identity` method in its interface.

Functors, also a shockingly simple concept hidden behind jargon.


Let me try Functor: You have a structure of values of some type. You want to apply a function to these values inside the structure, but you don't know how to do that. Luckily the structure itself does, so you just give your function to the structure and it applies it to its values for you. Structures that know how to apply functions to its values are called Functors.


I don't think it is jargon that makes understanding difficult. It is efforts required to develop a sense or intuition for those concepts. Like when you are looking at python list comprehensions and see list monad, looking at Go's `if err != nil then return err` and see Either monad and so on.

I've developed such intuition twice and it evaporated both times, when I wasn't using it for long enough.


I would love to read that post, the title describes exactly the boat I'm in :) how can I subscribe so I don't miss it?



> "Gilad Bracha covered this in a talk once."

Note that Bracha, knowledgeable as he is in his areas of interest, is painfully dismissive of things he does not understand. I watched that talk where he mentions monads (as well as non-optional static type systems, another subject he dislikes), and he comes across as ignorant and dismissive. I wouldn't use his opinions on these subjects as evidence of anything.


A monad is a standard interface for the Interpreter pattern.

That's why you would want it. That's what you gain from them. It is a very easy standard to implement if your interpreter is simple, it can be composed into more complex interpreters, and languages that support it come with many basic implementations that you can use to construct something more complex.

The mathematicians are saying basically the same thing, but from another point of view (monoid on the category of endofunctors means computations, with an environment, that you can join one after the other) that focus much more on standards than on usability, and much more on formality than on how to make large structures out of it, so the names are different.


> So it's a wrapper that implements a particular interface?

There's no wrapper, and "interface" is misleading since it suggests something that lets you invoke methods on instances whereas actually one of the core monad functions (pure aka point aka return) is something you call with a value that currently has no connection to the monad.

> Then why, oh why, do we have so many people who spout, "A monad is just a monoid in the category of endofunctors, what's the problem?"

The categorical thing is just a joke. It's hard to talk about monads in general because they're very generic, and unfortunately IO is one of the most "monadey" of them all: it's a monad and essentially nothing else. The best way to learn to work with IO is probably to learn to work with other monads first - option or either or writer or state, things that have a canonical presentation in terms of normal functions and values. Unfortunately, even though I/O is a tiny fraction of real-world business programming (when was the last time you actually used "getChar" at your day job?), it's where people tend to start programming.

> So it's a way of imperatively declaring execution sequence dependencies that lets you reason as if there's only pure functions most of the time. This seems to be the case for all functional programming languages/environments. When you get down to it, they're all, in the words of Garrison Keillor, "Pure, mostly."

You've got it backwards. It's a way of expressing operations that lets you reason as if you were calling imperative procedures most of the time, but they are and will always remain be pure functions in a guaranteed sense that you can fall back on. There is nothing "mostly" about it and this is really important, it's what makes functional programming so useful.


> There's no wrapper, and "interface" is misleading

True. I used a convenient lie to make a point. If you're interested in learning Monads you should definitely learn it from a proper source like Haskell from First Principles [0], an online course, or someone who really knows what they're talking about.

As I only alluded to and others have pointed out: there's nothing about monads that's inherently sequential or having to do with ordering operations. That's just how the language defined the interpretation of the IO monad. And it also happens that this is the primary topic of concern of TFA.

You might even come to realize that much of what a Monad isn't contradicts the entire premise of TFA... Haskell doesn't even need the IO monad and could implement IO other ways just fine [1].

[0] https://haskellbook.com [1] https://donsbot.wordpress.com/2009/01/31/reviving-the-gofer-...


> So it's a wrapper that implements a particular interface? Then why, oh why, do we have so many people who spout...

Its because its actually a mathematical concept. And that's the mathematical definition.

So Haskell decided to use the same name. Now some people feel, should I explain the math concept, or its concrete representation in Haskell.

Also, its a bit more involved as an interface. In that its not enough to implement the common methods for the interface. You also have to prove that your implementation for each exhibit certain properties, specifically there needs to be an identity value which act as a neutral element, and they must be associative.

Those laws are where things get more mathematical. Because its rare in comp-sci to talk about laws and properties of functions.


> Then why, oh why, do we have so many people who spout, "A monad is just a monoid in the category of endofunctors, what's the problem?"

It's a joke/dank maymay that Haskells still find funny long after it's pissed everyone else off.

The idea is that since category theory is described as "generalized abstract nonsense" by its practitioners, describing monads in terms of their strict category-theoretical definition helps no one, especially those new to Haskell. The problem is that unless your audience is steeped in category theory, they can't appreciate the irony of the situation and you just come off sounding like a dick.


> describing monads in terms of their strict category-theoretical definition helps no one, especially those new to Haskell.

I am a counterexample: the description of a monad as a monoid in the category of endofunctors actually helped me, especially when I was new to Haskell. I am a mathematician, and happen to know category theory enough to appreciate this description. Also, I am a little tired of hearing "you don't have to know category theory in order to learn Haskell". What if I already DO know category theory? I wish someone wrote a tutorial or a book explaining Haskell to mathematically inclined readers and not dismissing (in a kind of anti-intellectual way) simple algebra as "useless abstractions".


The problem is that unless your audience is steeped in category theory, they can't appreciate the irony of the situation

Who needs mindshare, when you can have in-jokes instead? Better to be the one everyone initially laughs at, but wind up with all the mindshare, than to be the one doing all the laughing who gets left behind.


It's not quite an in-joke. It's in-gallows humour: something common to all transmission of hard-to-communicate knowledge.

Anyone on the far side of a gulf of enlightenment—and understanding monads is an enlightenment, if a small one—knows that it's effectively impossible to actually communicate the particular thing they learned that helped them achieve enlightenment. (Well, it's not impossible to communicate what they learned; it's just that that's roughly useless to anyone else. An enlightenment is a realization that culminates only from all of a set of micro-skills being attained; and each person is missing different micro-skills to start with. You can look back and see the micro-skills you learned, and teach those, but you have no idea what micro-skills you started off already in possession of that others did not—what micro-skills you take for granted—and so you cannot teach those.)

When faced with someone starting on the path to an enlightenment, who asks you to simply summarize the path for them, there's no way to actually usefully tell them. But it's kind of rude to just say nothing—and on a forum like this, equally rude to assume a role of a master verbally lashing an apprentice (ala a Zen parable) for assuming they could understand the concept without working their brain up through all the micro-skills it was missing first.

So, what you do instead is, you make a joke. A joke that seems opaque at the time, but which the learner, having journeyed further down the path, will realize was the truth they sought, and exactly what they asked for—it was just a truth that was, necessarily, completely useless to them at the time. Any such truth would be.

You don't make the joke to be snarky. You make the joke because you wish that, this time, it would work, and the learner would skip the path and achieve the enlightenment; that you could just reach across the gulf and bring them over. But you know it won't. The punchline of the "joke" is not played on the learner, but on the teacher: it is that the world is cruel and to teach skills that require enlightenments is to suffer knowing your students lay across this gulf, and most of what you say will miss them entirely because of the mismatch in micro-skill acquisition between you.

(Though, I suppose, when the learner attempts to teach the concept themselves, and realizes the only thing they want to say is the same useless thing that was said to them—this would be the joke "paying off." That pay-off makes it sort of like a traditional joke, in the sense that choosing to "tell" it rather than simply thinking it to oneself is choosing to set the learner up for that later pay-off.)


I think this is one of the better explanations of why "enlightenment" in any field is so hard to get to, so hard to explain, yet so compulsively appealing to talk about. The framing around the joke really makes a lot of sense to me.

I'm tempted to share your writing on my other social channels! Excellently done!


An enlightenment is a realization that culminates only from all of a set of micro-skills being attained

There are lots of disciplines/areas of human knowledge and culture where most of the micro-skills have inherent rewards for learning them.

When faced with someone starting on the path to an enlightenment, who asks you to simply summarize the path for them, there's no way to actually usefully tell them.

I think that has to do more with not being motivated enough to try hard enough combined with the difficulty of summarizing. It's one thing to try to explain a paradigm-shifting insight or system to someone who has never paradigm shifted to learn something. The thing about Haskell outreach, are such failures even in the face of an audience who has previously undergone such a paradigm shift.

You don't make the joke to be snarky. You make the joke because you wish that, this time, it would work, and the learner would skip the path and achieve the enlightenment

How is this different from laziness? Smalltalkers similarly gave up trying to convey how their environment was different, many of them with such snarky jokes. Then years later, Chris Granger comes along with Light Table, and transmits what it is quite clearly and succinctly.


1. I perhaps forgot to mention a key thing about the enlightenment process. Most of the people being asked the question are those further down the path, but not further-down by much. Journeymen, not masters.

A journeyman is someone who has acquired all the micro-skills they were missing, and has thus gone on to achieve some level of intuitive grasp of the enlightenment they sought. They "grok" the skill.

A master is someone who has gone back and thoroughly weeded their mental garden of the micro-skills they started with and took for granted, and have begun (though perhaps not finished) replacing those with conscious learnings. The master desires to attain conscious handles onto each and every part of the mental schema or process they seek to understand, in order to understand the enlightenment-requiring mental skill as a system, rather than as a simple intuition.

A journeyman has a sense that they know the answer—that they "are enlightened"—and this sense works well enough to guide them when they seek to use the mental skill they sought to acquire. But, because they do not understand the enlightenment-requiring mental skill as a system, only as an intuition, they can give an apprentice on the path no answer that will satisfy them. This is the "gallows humour" stage of the path.

Yes, masters of the path will be able to guide apprentices. Zen koans are written by masters, and they are no gallows humour; they tilt the world enough to allow you to catch sight of the micro-skills the master was attempting to convey. (In the modern world of analytic philosophy, koans might even have a hope of being displaced by jargon-laden explanations that can be drudged through to bash the concept into one's head, like a maths textbook. That doesn't sound exciting, but it is!)

Light Table is such a koan, created by a master of the path of living-memory-image reflective systems, seeking to "tilt" as many parts of the system that Smalltalk is into the light as possible. (Granger's trick was contrasting those parts to a backdrop of regular, ugly concepts like Javascript and Electron that aren't part of the enlightenment-inspiring system. The concept-handles come clear at the visible seams of the Light Table system. Whereas, in Smalltalk itself, the seams aren't visible, because the system is coherent. You can't see the muscles of the perfect average face; it's too coherent to dissect.)

Putting this another way: most people who might be asked about something aren't teachers with education degrees. They're just students who already learned something and want to share what they learned. They fail because the thing is hard to share, and they don't have the skills about teaching required to realize what's making the thing hard to share and to fix it. (Those that do have such skills, but don't have the time to apply them to the concept—dissecting it and re-building it in a teachable-to-others form—usually just keep silent, rather than attempting to share their learning.)

> Haskell['s journeymen] are such failures [to teach the required micro-skills] even in the face of an audience who has previously undergone such a paradigm shift.

Ah, but have they? Many people have a natural mind for software engineering. They take for granted the concepts inherent in procedural code execution on a CPU or virtual machine; in parsing and lexing; even in pseudo-paradigms like OOP.

Indeed, it is the rare software engineer who actually experienced any paradigm shifts regarding Computer Science (for those of us that took a degree in it.) Usually it's "easy"—meaning natural—for those of an analytical mindset.

All, perhaps, except for that one class you have to take at the beginning of a CS curriculum, Discrete Maths. A lot of the SwEng "naturals" struggle at that. Because Discrete Maths is not the same thing as CS. Discrete Maths is, in fact, maths.

Mathematicians are used to paradigm shifts/"englightenments" (i.e. learning systematic skills requiring working knowledge of many micro-skills). Each subfield of mathematics is essentially named for the systematic skill required to comprehend work done under its aegis. Mathematicians who read work in various sub-fields, are used to quickly achieving a journeyman's competence in the relevant systematic skills. Mathematicians who specialize, who enter a sub-field, must necessarily become masters, if they have any hope of building upon that work. They must understand the required skill fully. (They must, by cute analogy, be able to build their Light-sabers from scratch.)

Most software engineers—including Haskellers—are not mathematicians. They have, other than that one time in Discrete Maths, never experienced the feeling of climbing toward an enlightenment. Even then, Discrete Maths is often the lowest grade for a lot of new CS students. They don't yet have this meta-skill of climbing toward enlightenments—of throwing themselves hard at formalized jargon using textbooks and references in an attempt to build a new systematic schema in their brain in just a few days. And they are almost never told that this is the true skill that their Discrete Maths course is there to impart into them. It's not about learning graph theory or whatever; that, just as much as a class on Operating Systems or VLSI or whatever else, is a practical, concrete skill for a software engineer. The Discrete Maths class in a CS program is about learning how to quickly learn those kinds of concepts. It's about discovering that these mental gulfs exist, and learning the skills required to cross one.

If only it was taught as such ;)

The reason Haskell is uniquely bad, here, is that Haskell was—perhaps problematically—constructed by mathematicians, people who had already crossed one such gulf. Haskell's design and ecosystem "reflects" enlightenment on category theory, somewhat like Smalltalk "reflects" enlightenment on living-memory-image OOP. Neither system teaches those skills, though. You don't need to cross the gulf of category-theory to intuit Haskell as a journeyman; you only do if you want to have the appreciation for the "coherent shape" of Haskell required to make coherence-preserving modifications to its feature-set.

---

The long and short of the way to communicate all the Haskell "stuff" efficiently, not just monads, is to:

1. give the learner the meta-skill of Being A Student Of Mathematics (i.e. becoming a journeyman in new systematic skills by poring over textbooks and doing problems);

2. throw a Category Theory textbook at the learner, who is now equipped to digest it.

Anything less is laziness—though not necessarily on the part of the teacher ;)


Light Table is such a koan, created by a master of the path of living-memory-image reflective systems

Two answers. 1) So then someone should create a Haskell Koan which has just as much popular appeal and broad intuitive popular understanding. But then again, not really, because: 2) Really, get off of this Koan nonsense. It was really just a very well thought out and effective demo which chose exactly the right way to get across the benefits of such a system.

Whereas, in Smalltalk itself, the seams aren't visible, because the system is coherent.

Oh, there are seams! And warts!

Indeed, it is the rare software engineer who actually experienced any paradigm shifts regarding Computer Science

Really? It sounds like you haven't experienced too many of those kinds of paradigm shifts. All you know is the math-y kind.

Haskell's design and ecosystem "reflects" enlightenment on category theory, somewhat like Smalltalk "reflects" enlightenment on living-memory-image OOP. Neither system teaches those skills, though.

Absolutely wrong. If you delve into the Smalltalk image and class library, it does teach you OOP!

The long and short of the way to communicate all the Haskell "stuff" efficiently, not just monads, is to:

1. give the learner the meta-skill...

2. throw a Category Theory textbook at the learner...

Either put up or shut up. Anyone can have an esoteric uber language off in a corner somewhere and tell themselves the world misunderstands them while circle jerking with like minded folks. Been there, done that. The whole world is chok full of little groups like that. Stopping at just that is not that which makes a difference in the world.

What you are saying seems to amount to: "We're awesome! We're the superior learners, which is why we're superior, but alas poor us, it also makes us suck at teaching." I call BS. It doesn't matter if your tools are superior, if their qualities and the community's qualities make them inherently inferior at gaining mindshare. Either they're so superior, everyone will take the time to adopt them, or they're not so superior that it really matters that much.

Try and produce stuff. Try and reach people. The world will see who succeeds. Simple as that.


> It sounds like you haven't experienced too many of those kinds of paradigm shifts. All you know is the math-y kind.

You know that HN readers are about the 99th percentile of "willingness to learn random new CS concepts", right? Most programmers know one language. In fact, most programmers have only ever worked for one company, on one product, for their whole productive careers so far. Your idea of an "average" programmer is, in fact, a rare programmer.

> If you delve into the Smalltalk image and class library, it does teach you OOP!

That is the exact equivalent of reading a textbook on the subject, except it's not presented in prerequisite order, so it's slightly harder to digest.

A system that teaches is a system that allows you to notice the micro-skills you're missing faster than a textbook. A textbook is the brute-force approach.

Smalltalk is not a system that teaches. It's just a system. You can get out what you put into delving through it, but you can do that just as well with any random system. To be pedagogical, a system has to accelerate that process.

> We're awesome! We're the superior learners, which is why we're superior, but alas poor us, it also makes us suck at teaching.

Er, no: people that "know Haskell" (category theory) generally suck at teaching Haskell (category theory) because people suck at teaching by default, because they haven't learned the meta-skill of teaching. And even those that do, haven't yet put in the effort to factor their mental-model of a given skill to turn it into a teachable skill.

The people that can teach you something about Haskell (category theory), are, y'know, teachers, that have learned Haskell (category theory) and then applied educational principles to their understanding of it in order to be able to teach it well.

Has nothing to do with Haskell, other than Haskell actually having a relatively-difficult skill in it for people coming from a SwEng background to learn. Other languages are easier or harder for such people to learn, because the skills they require are more or less natural given a SwEng background; and, comparatively, people with a CS or Physics or Electrical Engineering background have other backgrounds that make different languages have a different skill-gulf. Haskell (category theory) is easy for mathematicians. Assembly is easy for electrical engineers. Prolog is easy for DB systems programmers. Etc. Nothing special about any of them—they're just different points in knowledge-space, that different people start out closer or further from because of their backgrounds.

> Try and produce stuff.

I do! Not in Haskell, though. Despite writing the above, I have literally never used Haskell once in my life. I'm just talking about it as a specific application of the general principle of skill-gulfs.

> Try and reach people.

Why?

In all of the above, nobody ever said why anyone is trying to teach anyone else monads. Honestly, I think people just shouldn't bother. No "amateur teacher" is attempting to teach anyone else graph theory, or linear algebra, or the x86 ISA. Professional teachers, at universities, do that, because those are skills independent of any programming language. People generally understand that teaching these skills is the job of professional teachers, and that you have to apply yourself as a student, full-time, to learn them.

Well, category theory is such a skill.

In short: stop trying to teach people monads. Petition more schools to teach people monads (category theory), outside of the context of any particular language. Then Haskell is just a language, with no skill gulf.

To say that you should "reach people" with an explanation of monads, is like expecting RDBMS docs to "reach people" with an explanation of relational algebra. It's not their job. You're supposed to come in with that skill. Their job is to provide you a thing that you know you want—a solution for a problem you know you have—given that the skills you already possess give you the ability to evaluate that solution.


> "Who needs mindshare, when you can have in-jokes instead?"

It's a joke, but more importantly, it's a joke by and for people who are already familiar enough with Haskell. It's not a serious attempt at communicating something useful about the language; these attempts exist, but this joke is not one of them. Absolutely no-one makes this joke to beginners. You only make this joke to someone who already has an understanding of Haskell. It's not a common joke, either.

It's like those obfuscated C examples. Nobody uses them to teach beginners anything, and it'd be a mistake to ask "why do all these C programmers keep writing purposefully obfuscated code to scare beginners!?". Purposefully obfuscated C code, much like the Haskell joke, is not aimed at beginners.


> category theory is described as "generalized abstract nonsense" by its practitioners

That should be more accessible for people trying to learn it. The idea that "category" by itself is something that is supposed to be completely devoid of meaning is not clear at first. This slowed me down a lot when learning.


As a "never touched any functional language but always hear about how monads are extremely complex", I feel enlighted.


Realising that a monad is just a lax functor from a terminal bicategory also helps.


>So it's a way of imperatively declaring execution sequence dependencies that lets you reason as if there's only pure functions most of the time.

No. Monad is just a “design pattern”. It’s nice that this design pattern happens to be useful to force sequential evaluation, but it’s just one of the many things that fits the monad abstraction.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: