# Whatâs a functor?

## A functor is a list.

`map(function)(list) = [function(element) | element <- list]add1(input) = input + 1map(add1)([1,2,3])-- [2,3,4]`

## A functor is a function.

`map(function1)(function2)(input) = function1(function2(input))sub2(input) = input - 2map(add1)(sub2)(1)-- 0`

## A functor is a promise.

`map(function)(promise) = fmap(function)(promise)promise <- async(return 11)wait(map(sub2)(promise))-- 9`

## A functor is an effect that you lawfully define `map` for.

`map  ::       (input -> output) -- Takes a function.  -> effect(input          ) -- Takes input inside an effect.  -> effect(         output) -- Returns output inside an effect.`
• takes a function `input -> output` ,
• takes input for that function stuck inside an effect `effect(input)` ,
• passes the `input` to the function,
• collects the functionâs `output`,
• and returns the `output` stuck inside the effect `effect(output)` .

# Wait, what do you mean by âlawfully define?â

## Okay, whatâs the first law?

`list = [1,2,3]identity(input) = inputlist == map(identity)(list)-- True`

## Hmm, whatâs the second and last law?

`times3(input) = input * 3composition(input) = add1(sub2(times3(input)))composition(1)-- 2list = [1,2,3]map(composition)(list) == map(add1)(map(sub2)(map(times3)(list)))-- True`

# Can map accept a function with more than one parameter?

`add(left)(right) = left + rightmap(add)([1,2,3])-- [ add(1),--   add(2),--   add(3) ]`
`[ add(1),  add(2),  add(3) ]`

# What are applicative functors?

## An applicative functor is a list.

`pure(input) = [input]apply(functions)(list) =  [ element | function <- functions,              element  <- map(function)(list)  ]apply(pure(add1))([1,2,3])-- [2,3,4]apply(apply(pure(add))([1,2,3]))([4,5,6])-- [5,6,7,6,7,8,7,8,9]apply(map(add)([1,2,3]))([4,5,6])        -- [5,6,7,6,7,8,7,8,9]`
`apply(pure(add))([1,2,3])-- [ add(1),--   add(2),--   add(3) ]map(add)([1,2,3])-- [ add(1),--   add(2),--   add(3) ]`
`[   ] `apply` [1,2,3] `apply` [4,5,6]-- [][add] `apply` [     ] `apply` [4,5,6]-- [][add] `apply` [1,2,3] `apply` [     ]-- []`
`if_a_then_b_else_c(a)(b)(c) = if a then b else cpure(if_a_then_b_else_c) `apply` x `apply` y `apply` z`
`if_x_then_y_else_z([True])(["y result"])(["z result"])-- ["y result"]if_x_then_y_else_z([False])(["y result"])(["z result"])-- ["z result"]`
`if_x_then_y_else_z([True])(["y result"])(["z result"])-- ["y result"]`
• `[True]`
• `["y result"]`
• and `["z result"]`
`if_x_then_y_else_z([True])(["y result"])([])-- []`
`if_x_then_y_else_z(x)(y)(z) =  apply(pure(\ a -> if a then y else z))(x)if_x_then_y_else_z([True])(["y result"])([])                           -- [["y result"]]`

## An applicative functor is a function.

`pure(function)(ignore) = functionpure(add1)(Nothing)(0)-- 1apply(wrapped_function)(function)(input) =  map(wrapped_function(input))(function)(input)apply(pure(add1))(add1)(1)-- 3(pure(add) `apply` add1 `apply` add1)(1)-- 4`
`pure(add1)("Ignore this?")(1)-- 2pure(add1)(concat ["Ignore"," this?"])(1)-- 2`
`add_x_y_z(x)(y)(z) = add(add(x)(y))(z)add_x_y_z(2)(2)(2)-- 6(pure(add_x_y_z)`apply` add1`apply` add1`apply` add1)(1)-- 6`
• `1` gets added to `1` making `x` equal `2`
• `1` gets added to `1` making `y` equal `2`
• `1` gets added to `1` making `z` equal `2`
• and finally `x`, `y`, and `z` get added together for a total of `6`.
`apply(pure(add_x_y_z))(add1)(1)(2)(3)-- 7add_x_y_z(add1)(2)(3)-- 7`
`add1(input) = 1 + inputsub2(input) = 2 - input                                 sub3(input) = 3 - input                                 (pure(add_x_y_z) `apply` add1 `apply` sub2 `apply` sub3)(4)-- 2add1(4) + sub2(4) + sub3(4)-- 2(1 + 4) + (2 - 4) + (3 - 4)-- 2`
`first  = \ (a,b,c) -> a                                                               second = \ (a,b,c) -> b                                                              third  = \ (a,b,c) -> c new_add_x_y_z =  pure(add_x_y_z) `apply` first `apply` second `apply` third         new_add_x_y_z(1,2,3)-- 6`
`extract_then_add_x_y_z(t) =  add_x_y_z(first(t))(second(t))(third(t))               extract_then_add_x_y_z(1,2,3)-- 6`
`first  = \ (a,b) -> asecond = \ (a,b) -> bnew_add_x_y_z = pure(add_x_y_z) `apply` first `apply` secondnew_add_x_y_z(1,2)(3)                                         -- 6`

## An applicative functor is a functor that you lawfully define pure and apply for.

`pure  :: input         -- Takes some input.  -> effect(input) -- Returns it inside an effect.apply  :: effect(input -> output) -- Takes a function in an effect.  -> effect(input          ) -- Takes input in an effect.  -> effect(         output) -- Returns output in an effect.`
• takes a function inside an effect `effect(input -> output)`,
• takes input for that function inside an effect `effect(input)`,
• applies the function to the input,
• and returns the functionâs output inside the effect `effect(output)` .
`map  ::       (input -> output) -- Takes a function.  -> effect(input          ) -- Takes input inside an effect.  -> effect(         output) -- Returns output inside an effect.apply  :: effect(input -> output) -- Takes a function in an effect.  -> effect(input          ) -- Takes input in an effect.  -> effect(         output) -- Returns output in an effect.`
`map   ::  (i -> o) -> e(i) -> e(o)apply :: e(i -> o) -> e(i) -> e(o)--       ^ The big difference.`

# I still donât get applicative functor.

## What do you mean by independent effects?

`x = [1,2]y = [3,4]z = [5,6]pure(add) `apply` (pure(add) `apply` x `apply` y) `apply` z  -- [9,10,10,11,10,11,11,12]`
`[ 1+3+5=09,  1+3+6=10,  1+4+5=10,  1+4+6=11,  2+3+5=10,  2+3+6=11,  2+4+5=11,  2+4+6=12 ]`
`add1_inside_effect(input) = pure(input + 1)`
`pure(add1_inside_an_effect) `apply` x                    -- [[2],[3]]pure(add) `apply` (pure(add1_inside_an_effect) `apply` x)-- error!`

# What is a monad?

## A monad is a list.

`join(nested_lists) =  [element | list <- nested_lists, element <- list]join([[1], [2, 3], [4, 5, 6]])-- [1, 2, 3, 4, 5, 6]join(apply(pure(\ x -> [x + 1, 1]), [1,2,3]))-- [2, 1, 3, 1, 4, 1]join(  apply(    pure(\ x -> [2, x * 3, x * 4]))(    join(      apply(        pure(\ x -> [x + 1, 1]))(        [1,2,3]))))-- [2,6,8,2,3,4,2,9,12,2,3,4,2,12,16,2,3,4]`
`if_x_then_y_else_z =  pure(\ a -> if a then y else z) `apply` xif_x_then_y_else_z([True])(["y result"])([])                           -- [["y result"]]`
`if_x_then_y_else_z(x)(y)(z) =  join(pure(\ a -> if a then y else z) `apply` x)if_x_then_y_else_z(  [True,False,False,True])(  ["y result"])(  ["z result"])-- [ "y result",  True  so return y.--  "z result",   False so return z.--  "z result",   False so return z.--  "y result" ]  True  so return y.`

## A monad is a function.

`join(wrapped_function)(input) =  wrapped_function(input)(input)join(apply(pure(add))(add1))(1) -- 3add(add(1)(1))(1)-- 3add(2)(1)-- 3(1 + 1) + 1-- 3divide(numerator)(denominator) = numerator / denominatorjoin(  apply(    pure(divide))(    join(      apply(        pure(add))(        add1))))(2)-- 2.5divide(  add(    add(      1)(      2))(    2))(  2)-- 2.5divide(  add(    3)(    2))(  2)-- 2.5divide(  5)(  2)-- 2.5(((1 + 2) + 2) / 2)-- 2.5`
• The first function takes only one parameter.
• It receives the input and returns some output.
• The second function takes two parameters.
• It receives the output from function one, the input, and returns some output.
• The third function takes two parameters.
• It receives the output from function two, the input, and returns some output.
• The fourth functionâŚand on and on for how ever many functions you sequenced.

## A monad is an applicative functor that you lawfully define join for.

`join  :: effect(effect(data))  -> effect(data)`

# What about return and bind?

`bind(effect)(function) = join(apply(pure(function))(effect))[1,2,3] `bind` \ x -> [x + 2]-- [3,4,5][1,2,3] `bind` \ x -> [x + 2] `bind` \ y -> [y * 3]       -- [9,12,15][1,2,3] `bind` \ x -> pure(x + 2) `bind` \ y -> [y * 3, 0] -- [9,0,12,0,15,0](add1 `bind` add `bind` divide)(2)-- 2.5`
`bind(effect)(function) = join(map(function)(effect))[1,2,3] `bind` \ x -> pure(x + 2) `bind` \ y -> [y * 3, 0] -- [9,0,12,0,15,0]`
`return = pure`

# Can you summarize them for me?

• Functor lifts or upgrades a function, allowing it to operate on a single effect, leaving the effect intact after itâs done. It requires a lawful `map` definition.
• Applicative functor builds on or generalizes functor, allowing you to sequence multiple independent effects. It requires a lawful `pure` and `apply` definition.
• Monad builds on or generalizes applicative functor, allowing you to sequence independent and/or dependent effects. It requires a lawful `join` definition.
`map   ::  (i ->   o ) -> e(i) -> e(o) -- Functorapply :: e(i ->   o ) -> e(i) -> e(o) -- Applicativebind  ::  (i -> e(o)) -> e(i) -> e(o) -- Monad         ^      ^`

--

--

## More from Lettier

https://lettier.com

Love podcasts or audiobooks? Learn on the go with our new app.