Hi Yannick, thank for the feedback!
Rubens Pinheiro Gonçalves Cavalcante

Thanks for the link to Mr Elliot’s article! I’ve just answered to his article just to have his opinion about this here.

Yeah, so from what I understand from the definition of a Monad, flatMap expects a function of type a => Monad b` and returns a Monad b`

Here’s an example that underlines the difference between map and flatMap (inspired from Professor Frisby Introduces Composable Functional JavaScript by @drboolean) :

const Box = x => ({
map: f => Box(f(x)),
flatMap: f => f(x),
Box.of = x => Box(x)
const b = Box.of('hello')
console.log(b.map(str => str.toUpperCase()))
// Box('HELLO')
// f :: String -> Box String
const f = str => Box.of(str.toUpperCase())
// f is a function that takes a String and returns a Box(String)
// This is the correct type expected by flatMap
// Box('HELLO')
// the result is of type Box(String)
// Let's use the same function f with a map
// I can do it because map expects a function of type a -> b
// and f is of type String -> Box(String)
// Box(Box('HELLO'))
// the result is of type Box(Box(String))

This is why we talk about map and flatMap (hence the ‘flat’ in the name :) ) because flatMap solves the problem of nesting inside the Box that we would have with map.

But it does not flattens all the levels of nesting imho (multiple contexts as you say).

const b = Box.of(Box.of('hello'))
const f = str => Box.of(str.toUpperCase())
// throws an error because flatMap attempts to call .toUpperCase()
// on a Box(String)

If we wanted to flattens all the levels, we would need to call flatMap(x => x)` as many times as needed to have only one level of nesting.

Like what you read? Give Yannick Spark a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.