, 28 tweets, 6 min read Read on Twitter
Wow, these results are sobering. In an effort to turn them around, I’m going to attempt a Twitter #monadtutorial. I realize this has probably been done before, but here goes anyway... 1/
This will not be Haskell-focused. Haskell was my first introduction to monads back in 1999, and it just confused the heck out of me. Instead I’ll use examples from #csharp and #fsharp, since they’re what I know best. 2/
First, ignore category theory jargon. Unless you’re doing actual math (or Haskell), “Monad” as a concept is far less important than its practical applications. So let’s start with what monads are good for, before getting into what they are. 3/
Monads are useful for composing functions with a specific kind of type signature. In F# terms, it looks like T -> M<U> where M is some generic type. In C# it looks like Func<T, M<U>>. This is what @ScottWlaschin calls a “world-crossing” function. 4/ fsharpforfunandprofit.com/posts/elevated…
(That article series is excellent BTW, and you should read it after this thread because it goes in way more depth than I have time to do.) 5/
So you can chain functions together. That’s pretty abstract. What does this mean in practice? To answer that, let’s talk about what the type M typically is, at least in .NET. 6/
The most popular types for M (I’m guessing, I don’t have magical telemetry) are probably IEnumerable<T> and Task<T> (or Async<‘T> in F#). Other interesting types would be Lazy<T> and ‘T option in F#. 7/
You can think of these as “wrapper types” that add some behavior or aspect to a regular value. For example, Task<int> is a promise to return an int asynchronously. IEnumerable<double> yields zero or more doubles. string option gives you zero (None) or one (Some) string. 8/
Let’s take Task<T> in C# as an example. Say you have a bunch of async computations that you want to string together serially. You’d just use async/await, right? 9/
async/await is just syntactic sugar. At least conceptually, it boils down to taking a bunch of functions that return Task<T> and chaining them together. Sound familiar? 10/
Between each async computation, the “chaining” logic gets a now-completed task, unwraps its value (gets a T from an M<T>), and passes it to the next async computation (conceptually a function from T to M<U>). And so on it goes. 11/
Let’s look at IEnumerable<T> next. Actually, from now on I’m going to use F#’s name, seq<‘T>, because I’m tired of typing. 😈 12/
Imagine you have a couple string functions you want to glue together where the first tokenizes an input string, and the second returns synonyms of each token. Each of these has the signature string -> seq<string>. Look familiar? 13/
In C# you could write nested foreach loops, or you can use LINQ. In F# you’d use a sequence expression, which is the moral equivalent of LINQ in this case. 14/
LINQ and sequence expressions have something in common: Both are syntactic sugar. Just like async/await and the F# async computation expression are syntactic sugar. A pattern is emerging... 15/
And that, to the best of my non-Haskeller brain’s understanding, is what makes a Monad useful: It enables syntactic sugar that hides some cross-cutting detail (async-ness, sequence-ness), leaving behind what looks more like straight-line code. 16/
So what is a Monad, in non-mathy terms? It’s basically a type plus two pure functions that obey certain laws. I won’t go into details on the laws, but here’s the crux of it... 17/
If M<T> is the type, then one of the functions, called “return” by convention, has the signature T -> M<T> and it just wraps a regular value. Think Task.FromResult in C#, or new[] { x } 18/
The other function is where the magic happens, and it’s called “bind” in the FP world. In C# it’s called SelectMany and is part of LINQ. Its signature is M<T> -> (T -> M<U>) -> M<U>. Let’s unpack that... 19/
Let’s use SelectMany as an example. It’s an extension method called on an enumerable of T, so that’s the first parameter. The second parameter is a function that takes a single T and returns an enumerable of U. Finally, SelectMany itself returns an enumerable of U. 20/
Since the result type of SelectMany isn’t an enumerable of enumerables of U, that means that it must “flatten” the intermediate results into a single sequence. Sometimes you’ll see this called “flatMap” in other languages, even for non-collection types. 21/
I’m not going to attempt to explain the mechanics of how return and bind/flatMap can be used to implement fancy syntactic sugar. If you’re really curious, this article series by @ScottWlaschin explains how it works for #fsharp computation expressions: fsharpforfunandprofit.com/series/computa… 22/
Computation expressions in #fsharp are very powerful. This is why F# supports sequence expressions and async workflows as essentially libraries, where C# needed its syntactic sugar for LINQ, iterators, and async/await baked into the compiler. 23/
This is the true power of monads — In a language like F# or Haskell, you can reuse the common syntactic sugar mechanism (CEs or do-notation, respectively) with your own data types. All you need is return and bind. 24/
My favorite example: Generating arbitrary test data for property-based tests using the “gen” workflow in F#. It’s implemented as part of FsCheck. 25/
In summary: A monad is a pattern that enables syntactic sugar for cross-cutting concerns like laziness, asynchrony, optionality, “Collection-ness”, or whatever you want (loggability, arbitrariness/randomness, etc.). All you need is a type and two special functions. 26/
...and a language that doesn’t suck. 😈
/fin
Missing some Tweet in this thread?
You can try to force a refresh.

Like this thread? Get email updates or save it to PDF!

Subscribe to Bruce Johnston
Profile picture

Get real-time email alerts when new unrolls are available from this author!

This content may be removed anytime!

Twitter may remove this content at anytime, convert it as a PDF, save and print for later use!

Try unrolling a thread yourself!

how to unroll video

1) Follow Thread Reader App on Twitter so you can easily mention us!

2) Go to a Twitter thread (series of Tweets by the same owner) and mention us with a keyword "unroll" @threadreaderapp unroll

You can practice here first or read more on our help page!

Follow Us on Twitter!

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just three indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3.00/month or $30.00/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!