cory brown

@uniqname

@365JSThings

Nav

In less than 15 minutes, you will understand monads

You
likely already

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.

Douglas Crockford; Monads and Gonads

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

https://en.wikipedia.org/wiki/Monad_(functional_programming)

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

What is a Monad?

(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

Left Identity

Right Identity

Lazy Evaluation

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.

But why?

Encapsulation

Monads are about encapsulating a particular kind of work.

Encapsulation

There are many different types of monads.

Each type encapuslates a particular type of work

for instance

Log Monad

Log<T>

The Log Monad encapsulates logging.

 

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 Monad

Log<T>

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

Log Monad

Log<T>

Log(42)
  .map(add(5))
  .map(less(3))

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

Maybe Monad

Maybe<T>

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

 

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

Maybe Monad

Maybe<T>

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

Maybe Monad

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 Monad

Either<T>

The Either monad encapsulates branching.

 

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 Monad

Either<T>

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

Either Monad

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'))

fin.

In less than 15 minutes, you will understand monads

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.

  • 92
Loading comments...

More from Cory Brown