This post is not about Monads but the teaching of Monads. A vital part of software engineering within an organization is workforce development or training. Often this is informal and occurs individually or in small groups. Sometimes organizations mandate mentoring, and they may also formalize a training process or common body of knowledge that should be the baseline for developers in the organization. In this post, I’m taking a subject that is sometimes seen as a “deep” concept of functional programming (Monads) and reviewing approaches for introducing others to this concept.
What Is a Monad?
First, let me provide a very brief description of a monad while attempting to avoid any in depth discussion or training on monads (explanation approaches are listed below and extensive discussions can be found in the links).
Monads represent a basic pattern of pipelining or chaining computation on a particular data type. This chaining can simplify otherwise cumbersome or complex series of logic (sometimes involving side effects) by providing special chaining or binding logic. Basic operations required for monads include a way to construct the data type, a way to convert the data type into the monad type, and a way to chain pieces of computation on the monad type together.
A Few Ways to Approach Monads
Approach(es) #1 – The Sillies
These are what I would consider to be the silly approaches. However, they are actually sprinkled throughout discussions of monads for beginners.
- Monads are easy, natural, and obvious. And here, I’ll give you a very complicated and obscure example to demonstrate why you should just understand monads ex nihilo…blah, blah, blah…so you get it now, right? Umm, no.
- Monads come from category theory in mathematics. Not many of us really understand category theory, but I’ll stumble through an explanation, then I’ll try to somehow tie it to monads and maybe you’ll find some benefit in it, somehow. Or maybe not.
Approach #2 – Side Effects
This approach explains monads as FP’s way of dealing with side effects. The example used in this approach is often IO (e.g. the IO monad in Haskell). While side effects may be handled using monads, I wonder if this approach to explaining monads is too narrow, leaving the learner unsure of how she might use monads for herself. This approach may retain monads as black boxes in the learner’s mind, not to be explored until much later in a programming career.
Approach #3 – Constructor, Unit, Bind
This approach focuses on the mechanics of monads and attempts to show the syntax and some examples. Done with the right sample code, analogies, and care, I believe this can be effective.
This approach might use a state monad as an example, or perhaps something like a null value (or Maybe in Haskell). Once the learner understands a concrete example, he may go on to others and realize that the pattern here is pipelining, and that the framework can be reused in several other contexts.
Approach #4 – Pipelining
Unlike the previous approach, this one starts with a conceptual approach, explaining monads in the abstract as pipelines before showing concrete examples. The danger here is that the learner is lost in the abstract and only starts to “get it” when things get more concrete. However, by emphasizing the general concept, the learner may be better equipped to quickly determine where in a system the monad pattern may be useful.
This is the approach I prefer; however, it’s fairly subjective and probably a personal preference. While approach #3 presents monads in concrete terms and gradually derives more abstract notions, this approach works in the opposite direction. Some learners may prefer one while others may prefer the other.
A Sampling of Links
Basic monad explanations (in my opinion, the most popular answers don’t seem to be geared toward beginners)
Haskell sources with sections on monads