#readwise # Monads <div> <img src="https://blog.ploeh.dk/content/binary/functors-applicatives-monads.png" style="background: white; padding: 10px; width: 250px" /> </div> ## Metadata - Author: [[Mark Seemann]] - Full Title: Monads - URL: https://blog.ploeh.dk/2022/03/28/monads/ ## Summary This is article is a part of a bigger blog series that covers various topics from category theory. The series includes other articles on the topic of functors. Here's a list, retrieved on March 17, 2023. - [[Kleisli composition]] - [[Monad laws]] - [The List monad](https://blog.ploeh.dk/2022/04/19/the-list-monad) - [The Maybe monad](https://blog.ploeh.dk/2022/04/25/the-maybe-monad) - [An Either monad](https://blog.ploeh.dk/2022/05/09/an-either-monad) - [[The Identity monad]] - [The Lazy monad](https://blog.ploeh.dk/2022/05/30/the-lazy-monad) - [Asynchronous monads](https://blog.ploeh.dk/2022/06/06/asynchronous-monads) - [The State monad](https://blog.ploeh.dk/2022/06/20/the-state-monad) - [The Reader monad](https://blog.ploeh.dk/2022/11/14/the-reader-monad) - [The IO monad](https://blog.ploeh.dk/2023/01/09/the-io-monad) - [[Test Data Generator Monad]] ## Highlights <div> <img src="https://blog.ploeh.dk/content/binary/functors-applicatives-monads.png" style="background: white; padding: 10px; width: 400px" /> </div> --- **All monads are [[Applicative Functors]], but not all applicative functors are monads. As the set diagram reiterates, applicative functors are functors, but again: not necessarily the other way around.** ([View Highlight](https://read.readwise.io/read/01gvzswr23kbrymbn69wmfzzzt)) --- When working with functors, you sometimes run into situations where the containers nest inside each other. Instead of a `Functor<decimal>`, you may find yourself with a `Functor<Functor<decimal>>`, or maybe even an object that's thrice or quadruply nested. If you can flatten such nested functor objects to just `Functor<T>`, then that functor also forms a monad. ([View Highlight](https://read.readwise.io/read/01gvzsxtsgnpydqfhsjrf236e3)) ^2ilhw4 --- **Usually**, however, **you don't see monads introduced via `join` or `Flatten`. It's a shame, really, because it's the most straightforward description.** ([View Highlight](https://read.readwise.io/read/01gvzszwrvw66dj61wv54xnm2y)) ^dbujzg --- Most languages that come with a notion of monads define them via a function colloquially referred to as *monadic bind* or just *bind*. In C# it's called `SelectMany`, [F# computation expressions](https://docs.microsoft.com/dotnet/fsharp/language-reference/computation-expressions) call it `Bind`, and Scala calls it `flatMap` (with a vestige of the concept of flattening). ([View Highlight](https://read.readwise.io/read/01gvzt10hk41cjqzm836fydj4j)) --- It looks almost like a functor's `Select` method (AKA `map` or `fmap` function). The difference is that this `selector` returns a functor value (`Functor<TResult>`) rather than a 'naked' `TResult` value. When a `Flatten` (or `Join`) method already exists, you can always implement `SelectMany` like this: ```csharp public static Functor<TResult> SelectMany<T, TResult>( this Functor<T> source, Func<T, Functor<TResult>> selector) { Functor<Functor<TResult>> nest = source.Select(selector); return nest.Flatten(); } ``` ([View Highlight](https://read.readwise.io/read/01gvzt2x962cyvz7jy9sw6kr1x)) --- You can use `SelectMany` like this: `Functor<TimeSpan> source = Functor.Return(TimeSpan.FromMinutes(32));` `Functor<double> dest = source.SelectMany(x => Functor.Return(x.TotalSeconds + 192));` The lambda expression returns a `Functor<double>`. Had you called `Select` with this lambda expression, the result would have been a nested functor. `SelectMany`, however, flattens while it maps (it *flatMaps*). (This example is rather inane, since it would be simpler to use `Select` and omit wrapping the output of the lambda in the functor. The later articles in this series will show some more compelling examples.) ([View Highlight](https://read.readwise.io/read/01gvzt59fvs6ddqjn4fddw9b31)) --- If you already have `Flatten` (or `Join`) you can always implement `SelectMany` like this. Usually, however, languages use monadic bind (e.g. `SelectMany`) as the foundation. Both C#, Haskell, and F# do that. In that case, it's also possible to go the other way and implement `Flatten` with `SelectMany`. ([View Highlight](https://read.readwise.io/read/01gvzt62r1zvfm07n3z0ah4xwg)) --- **The ability to flatten nested functors is the essence of what a monad is.** There are, however, also some formal requirements. As is the case with functors, there are laws that a monad should obey. ([View Highlight](https://read.readwise.io/read/01gvztb8n8qryke1ahe75hktgh)) --- Another requirement is that in addition to `SelectMany`/`bind`/`flatMap`/`>>=` a monad must also provide a method to 'elevate' a value to the monad. This function is usually called *return*. ([View Highlight](https://read.readwise.io/read/01gvztbphpvb4ma3p9y388nte8)) --- **A monad is a functor you can flatten.** That's the simplest way I can put it. ([View Highlight](https://read.readwise.io/read/01gvztd0kwn11fqw8tj118dq5s)) ^se5abr ---