# do

Monads are (in)famously said to be cursed.

"Once one understands what a Monad is, one loses the ability to explain it to others."

This is has become something of a self fulfilling prophecy. Today, we are going to break that curse.

A monad may encapsulate values of a particular data type, creating a new type associated with a specific additional computation

`String`
`Monad[String]`
``````// String
'a string'``````
``[] // <- Box``
``````// [String]
// AKA string in a box
['a string'] ``````
``````// String -> Number
const strLength = (str) =>
str.length``````
``strLength(['a string'])``

🚫

``strLength(['a string'])``
``['a string'].map(strLength)``

# Functor

``[🤷‍♀️].map(strLength)``
``[🤷‍♀️].map(strLen)``
``[fetchString...].map(strLen)``
``[🤷‍♀️].map(strLen)``
``fetch('/string')``
``.map(strLen)``
``.then(strLen)``
``[🤷‍♀️].map(strLength)``
``````const getVal = () =>
Promise.resolve(42)``````
``getVal().then(add(5))``

# Breaking The Curse

(It's a container for a value that does some defined bit of work in addition to passing that value to a function.)

# Could you explain a Monad to someone?

(It's a container for a value that does some defined bit of work in addition to passing that value to a function.)

# Of course there's more to Monads than that.

but those other bits are not what's hard to understand about Monads.

# Associativity

## Promises are not, strictly speaking, monads.

but they are close enough and demonstrate the core principles of monads quite nicely.

# Look for that extra bit of work it encapsulates

if something is described as a monad,
you know what to look for.

# for instance

## Log<T>

Logging is a side effect since it is observable outside of the function execution (it prints to the screen).

In functional programming, side effects are encapsulated in Monads like Log and others.

## Log<T>

``````const Log = (value) => ({
map: (fn) => {
const val = fn(value)
console.log(`Log[\${val}]`)
return Log(val)
}
})
``````

## Log<T>

``````Log(42)
.map(less(3))

//> Log[47]
//> Log[44]
``````

## Maybe<T>

The Maybe monad encapsulates nullish checks (null, undefined).

Maps are skipped for nullish values and executed for non-nullish values.

## Maybe<T>

``````const Maybe = (value) => ({
map: (fn) => Maybe(
value == null
? value
: fn(value)
)
})``````

## Maybe<T>

``````const obj = {
some: {
deep: {
property: 5
}
}
}

Maybe(obj)
.map(getProp('some'))
.map(getProp('deep'))
.map(getProp('property'))

// Just(5)
``````
``````const obj = {}

Maybe(obj)
.map(getProp('some'))
.map(getProp('deep'))
.map(getProp('property'))

// Nothing()``````

## Either<T>

Often, Either is used to branch on "correct" and error values, but it can be used for any kind of binary branching (a || b).

## Either<T>

``````const Either = (value) => ({
map: (predicate = isError, left = Error, right = id) =>
predicate(value)
? Right(right(value))
: Left(left(value))
})
``````

## Either<T>

``````const json = `{
"data": [1, 2, 3]
}`

Either(parseJson(json))
.map(getProp('data'))

// Right([1, 2, 3])

``````
``````const json = `{
"data": [1, 2,
}`

Either(parseJson(json))
.map(getProp('data'))

// Left(Error('SyntaxError'))

``````

By Cory Brown

# In less than 15 minutes, you will understand monads

Monads are (in)famously said to be cursed. Once one understands what a Monad is, one loses the ability to explain it to others. This is has become something of a self-fulfilling prophecy. Today, we are going to break that curse.

• 169