
There comes a point in every Functional Programmer's life where they feel the curse of the Monad has lifted and they must now explain Monads to their friends who just don't get it. What follows is probably wrong and confusing, cause there is no escaping the curse. But here goes...

Suppose you have a system property that contains the name of another system property, like:

```bash
KEYNAME=FOO
```

And you want the value of `FOO`, like:

```bash
FOO=BAR
```

So there is a chain of operations. We need to first lookup the `KEYNAME` value and then use that to lookup another value.

In a non-functional world you may do something like:

```scala
String prop = null;
String keyname = system.getProperty("KEYNAME");
if (keyname != null) {
  prop = system.getProperty(keyname);
}
```

In the functional world we can instead use a type that represents the nullable value, usually called an `Option`, like:

```scala
val maybeKeyname: Option[String] = sys.props.get("KEYNAME")
```

Now we can't use the `maybeKeyname` to lookup the second value because it might be `None` and `props.get` doesn't take an `Option`:

```scala
sys.props.get(maybeKeyname) // this won't work
```

So we need to chain together two options. We can do this with Monads via a `flatMap` function:

```scala
val maybeProp: Option[String] = maybeKeyname.flatMap(keyname => sys.props.get(keyname))
```

Since `flatMap` takes a function we can also just do:

```scala
maybeKeyname.flatMap(sys.props.get)
```

But there is some syntactic sugar for Monads in Scala that we can use on anything that has the shape of a Monad (i.e. _Monadic_):

```scala
val maybeProp: Option[String] = for {
  keyname <- sys.props.get("keyname")
  prop <- sys.props.get(keyname)
} yield prop
```

The _for comprehension_ makes Monad chaining look like a chain. So when you hear the word _Monad_ just think _chainable_ instead.

There are many different chainable types. Another is a `Try` for things that can fail.

For example, if we want to ask a user for two numbers and add them together, but handle number parsing failures we can do this:

```scala
import scala.io.StdIn
import scala.util.Try

for {
  num1 <- Try(StdIn.readLine("Number 1: ").toInt)
  num2 <- Try(StdIn.readLine("Number 2: ").toInt)
} yield num1 + num2
```

If you enter two numbers you get a `Success` but if either number is not an integer then the result will be a `Failure`.

Another Monadic type is `Future` which may hold a value later (i.e. async). You can chain futures together like `Option` and `Try`, for example:

```scala
import scala.concurrent.{Promise, Future}
import scala.concurrent.ExecutionContext.Implicits.global

// a Promise provides a place we write a value to later
val p1 = Promise[String]()
val p2 = Promise[String]()

val nameFuture: Future[String] = for {
  first <- p1.future
  last <- p2.future
} yield first + " " + last

// nameFuture does not yet have a value so lets write a value to the first Promise
p1.success("james")

// still no value for nameFuture because p1 and p2 are chained together and p2 doesn't have a value yet
p2.success("ward")

// ok, now nameFuture has a value - which you can print
nameFuture.foreach(println)
```

Monads just help us chain together operations on items in some form of container. In these examples the chains have been short (two operations) but could be much longer - making the value more apparent.
