SlideShare a Scribd company logo
1 of 198
Download to read offline
Dr Frankenfunctor and
the Monadster
@ScottWlaschin
fsharpforfunandprofit.com/monadster
Warning
This talk contains:
– gruesome topics
– strained analogies
– discussion of monads
Not suitable for sensitive people (seriously)
Functional programmers
love composition...
A functionInput Output
function A function BCompose
function A function B
function A and B
Easy!
... But here is a challenge for
function composition
function AInput Output
function BInput
Output 1
Output 2
function C
Input 1 Output 1
Output 2Input 2
function D
Input 1 Output
Input 2
function AInput Output
function BInput
Output 1
Output 2
function D
Input 1 Output
Input 2
How to
compose?
function AInput Output
function BInput
Output 1
Output 2
function D
Input 1 Output
Input 2
How to
compose?
The answer: monads!
The spread of the monad
• 1990 ACM Conference on LISP and Functional Programming
First monad in captivity
The terrible events at the 1990 ACM Conference on
LISP and Functional Programming
The spread of the monad
• 1990 ACM Conference on LISP and Functional Programming
• 1991 Eugenio Moggi, "Notions of computation and monads"
• 1992 PhilipWadler, "Monads for Functional Programming"
• 1999 Noel Winstanley, "What the hell are Monads?"
• 2004 Greg Buchholz, "Monads in Perl"
• 2005 Eric Kow, "Of monads and space suits"
• 2006 Eric Kow, Monads as nuclear waste containers
• 2009 James Iry, "A monad is just a monoid in the category of endofunctors,
what's the problem?"
• It’s everywhere now
The spread of the monad
• 1990 ACM Conference on LISP and Functional Programming
• 1991 Eugenio Moggi, "Notions of computation and monads"
• 1992 PhilipWadler, "Monads for Functional Programming"
• 1999 Noel Winstanley, "What the hell are Monads?"
• 2004 Greg Buchholz, "Monads in Perl"
• 2005 Eric Kow, "Of monads and space suits"
• 2006 Eric Kow, Monads as nuclear waste containers
• 2009 James Iry, "A monad is just a monoid in the category of endofunctors,
what's the problem?"
• It’s everywhere now
No wonder people think
monads are dangerous
The secret history of the monad
• 1816 Dr Frankenfunctor creates the Monadster
• 1990 ACM Conference on LISP and Functional Programming
• 1991 Eugenio Moggi, "Notions of computation and monads"
• 1992 PhilipWadler, "Monads for Functional Programming"
• 1999 Noel Winstanley, "What the hell are Monads?"
• 2004 Greg Buchholz, "Monads in Perl"
• 2005 Eric Kow, "Of monads and space suits"
• 2006 Eric Kow, Monads as nuclear waste containers
• 2009 James Iry, "A monad is just a monoid in the category of endofunctors,
what's the problem?"
• And 100's more
The topic of this talk
The story of the Monadster
The creature was built from body parts of various shapes
The various parts were assembled into a whole
The body was animated in a single instant, using a
bolt of lightning to create the vital force.
...The Monadster
The “mark of the
lambda”
But how was it done?
I have devoted many years of
research into this matter...
At last, I can reveal the secret
techniques of Dr Frankenfunctor!
Warning: These are powerful techniques and can be
used for good or evil...
I know of a young, innocent developer
who was traumatized for life.
Dr Frankenfunctor's toolbox
1. Modelling with pure functions
2. Wrapping a function in a type
3. Transforming parts into other parts
4. Combining two parts into one
5. Combining live and dead parts
6. Chaining “part-creating” functions together
7. A general way of combining any number of parts
I don’t expect you to remember all this!
Goal is just to demystify and give an overview
Technique 1:
Modelling with pure functions
Become alive!
Vital force
Dead part Live part
Don't try this at home
Live body part
Vital force
Become alive!
Remaining vital force
Dead body part
Two inputs
Live body part
Vital force
Become alive!
Remaining vital force
Dead body part
Two outputs
Live body part
Vital force
Become alive!
Remaining vital force
Dead body part
Less vital force
available afterwards
Live body part
Vital force
Become alive!
Remaining vital force
Dead body part
No globals,
no mutation!
But now you have two
problems...
Live part B
Vital force
Become alive B!
Remaining vital force
Dead part B
Live part A
Vital force
Become alive A!
Remaining vital force
Dead part A
How to connect the force
between two steps?
Live part B
Vital force
Become alive B!
Remaining vital force
Dead part B
Live part A
Vital force
Become alive A!
Remaining vital force
Dead part A
How to combine
the two outputs?
Technique 2:
Wrapping the "Become Alive" function
Also, introducing schönfinkelling
Moses Schönfinkel
invented schönfinkelling
Moses Schönfinkel
invented schönfinkelling
Haskell Curry
gave his name to currying
Input A
Uncurried
Function
Input B
Output C
Curried
Function
Input A
Intermediate
Function
Output CInput B
What is currying?
after currying
Currying means that *every* function has one input
// naming a lambda
Func<int,int> add1 = (y => 1 + y)
// using it
var three = add1(2)
Currying examples
// naming a lambda
let add1 = (fun y -> 1 + y)
// using it
let three = add1 2
Currying examples
// returning a lambda with baked in "x"
let add x = (fun y -> x + y)
// creating an intermediate function
let add1 = add 1 // (fun y -> 1 + y)
// using it
let three = add1 2
Currying examples
// "inlining" the intermediate function
let three = (add 1) 2
// returning a lambda with baked in "x"
let add x = (fun y -> x + y)
Currying examples
// removing the parens
let three = add 1 2
Currying examples
// returning a lambda with baked in "x"
let add x = (fun y -> x + y)
Live part A
Vital force
Become alive!
Remaining vital force
Dead part A
Currying "become alive!"
Become alive!
Dead part A Vital force
Live part A
Currying "become alive!"
Become alive!
Dead part A Vital force
M<Live Part A>
Live part A
Wrapping the function
"M" is for "Monadster"
Become alive!
Dead part A Vital force
M<Live Part A>
Live part A
Wrapping the function
Dead part A
M<Live Part A>
Create step in
recipe
Wrapping the function
An "M-making" function
Remember --
this is *not* a live part ,
it's a "potential" live part
M<Live Part A> Run
Live part A
Remaining vital force
Running the function
Vital force
M<Live Part A> Run
Live part A
Remaining vital force
Running the function
Vital force
Become alive!
Vital force
Live part A
M<Live Part A>
Show me the code
Left Leg
let makeLiveThingM deadThing =
// the inner one-argument function
let becomeAlive vitalForceInput =
... do stuff
... return two outputs
// wrap the inner function in the "M" wrapper
M becomeAlive
Creating M-things
let makeLiveThingM deadThing =
// get essence of dead thing
let essence = getEssenceOfDeadThing deadThing
// the inner one-argument function
let becomeAlive vitalForceInput =
// get a unit of vital force
let unitOfForce, remainingForce = getVitalForce vitalForce
// create a live thing
let liveThing = new LiveThing(essence, unitOfForce)
// return the live thing and remaining force
(liveThing, remainingVitalForce) // return a pair
// wrap the inner function in the "M" wrapper
M becomeAlive
Creating M-things
let makeLiveThingM deadThing =
// get essence of dead thing
let essence = getEssenceOfDeadThing deadThing
// the inner one-argument function
let becomeAlive vitalForceInput =
// get a unit of vital force
let unitOfForce, remainingForce = getVitalForce vitalForce
// create a live thing
let liveThing = new LiveThing(essence, unitOfForce)
// return the live thing and remaining force
(liveThing, remainingVitalForce) // return a pair
// wrap the inner function in the "M" wrapper
M becomeAlive
Creating M-things
let makeLiveThingM deadThing =
// get essence of dead thing
let essence = getEssenceOfDeadThing deadThing
// the inner one-argument function
let becomeAlive vitalForceInput =
// get a unit of vital force
let unitOfForce, remainingForce = getVitalForce vitalForce
// create a live thing
let liveThing = new LiveThing(essence, unitOfForce)
// return the live thing and remaining force
(liveThing, remainingVitalForce) // return a pair
// wrap the inner function in the "M" wrapper
M becomeAlive
Creating M-things
let makeLiveThingM deadThing =
// get essence of dead thing
let essence = getEssenceOfDeadThing deadThing
// the inner one-argument function
let becomeAlive vitalForceInput =
// get a unit of vital force
let unitOfForce, remainingForce = getVitalForce vitalForce
// create a live thing
let liveThing = new LiveThing(essence, unitOfForce)
// return the live thing and remaining force
(liveThing, remainingVitalForce) // return a pair
// wrap the inner function in the "M" wrapper
M becomeAlive
Creating M-things
let makeLiveThingM deadThing =
// get essence of dead thing
let essence = getEssenceOfDeadThing deadThing
// the inner one-argument function
let becomeAlive vitalForceInput =
// get a unit of vital force
let unitOfForce, remainingForce = getVitalForce vitalForce
// create a live thing
let liveThing = new LiveThing(essence, unitOfForce)
// return the live thing and remaining force
(liveThing, remainingVitalForce) // return a pair
// wrap the inner function in the "M" wrapper
M becomeAlive
Creating M-things
let makeLiveThingM deadThing =
// get essence of dead thing
let essence = getEssenceOfDeadThing deadThing
// the inner one-argument function
let becomeAlive vitalForceInput =
// get a unit of vital force
let unitOfForce, remainingForce = getVitalForce vitalForce
// create a live thing
let liveThing = new LiveThing(essence, unitOfForce)
// return the live thing and remaining force
(liveThing, remainingVitalForce) // return a pair
// wrap the inner function in the "M" wrapper
M becomeAlive
Creating M-things
makeLiveThingM : DeadThing -> M<LiveThing>
// create DeadLeftLeg
let deadLeftLeg = DeadLeftLeg "Boris"
// create a M<LiveLeftLeg>
let leftLegM = makeLiveLeftLegM deadLeftLeg
// potential leg only!
// now pretend that vital force is available
let vf = {units = 10}
// make a real left leg by running leftLegM
let liveLeftLeg, remainingForce =
runM leftLegM vf
// output:
// liveLeftLeg : LiveLeftLeg =
// LiveLeftLeg ("Boris",{units = 1})
// remainingForce : VitalForce = {units = 9}
Demo – Left Leg
Technique 3:
Transforming live parts
A Broken Arm
Dead Broken Arm
What we've got
Live Healed Arm
What we want
Healing a broken arm
Live Healed ArmLive Broken Arm HealBrokenArm
We have this function!
Live Healed Arm
...But we want one of these!
How can we get it?
Healing a broken arm
Dead Broken Arm
We have one of these...
Create
Dead Broken Arm Dead Healed Arm
Live Healed Arm
Healing a broken arm
HealBrokenArm
Create
Dead Broken Arm Dead Healed Arm
Live Healed Arm

No. We can only heal live arms
Healing a broken arm
HealBrokenArm
Dead Broken Arm
Live Healed ArmLive Broken Arm
Create
HealBrokenArm
Healing a broken arm
Dead Broken Arm
Live Healed ArmLive Broken Arm
Create
HealBrokenArm
No. We can't create live things
directly, only M-type things

Healing a broken arm

Dead Broken Arm
M<Live Healed Arm>M<Live Broken Arm>
Create
HealBrokenArm
Healing a broken arm
Dead Broken Arm
M<Live Healed Arm>

M<Live Broken Arm>
Create
HealBrokenArm
No. "HealBrokenArm" doesn't
work on M-type things

Healing a broken arm
Dead Broken Arm
M<Live Healed Arm>M<Live Broken Arm>
Create
HealBrokenArmM
We need a special "HealBrokenArmM"
that works on M-type things


Where can we get it from?
Healing a broken arm
Live Healed ArmLive Broken Arm HealBrokenArm
Healing a broken arm
M<Live Healed Arm>M<Live Broken Arm> HealBrokenArmM
This is what we’ve got
This is what we want
Live Healed ArmLive Broken Arm HealBrokenArm
Healing a broken arm
M<Live Healed Arm>M<Live Broken Arm> HealBrokenArmM
map
"map" is generic for M-things
NormalWorld
a b
"map" is generic for M-things
NormalWorld
a b
map
"map" is generic for M-things
NormalWorld
a b
map
World of M<_> things
M<a> M<b>
A function in the world of M-things
“lifting”
Show me the code
Broken Arm and "map"
let map f bodyPartM =
// the inner one-argument function
let becomeAlive vitalForce =
// get the input body part by running the M-thing
let bodyPart,remainingVitalForce =
runM bodyPartM vitalForce
// transform the body part using the function
let transformedBodyPart = f bodyPart
// return the transformed part and remaining force
(transformedBodyPart, remainingVitalForce)
// wrap the inner function in the "M" wrapper
M becomeAlive
Transformation function
M-thing to transform
let map f bodyPartM =
// the inner one-argument function
let becomeAlive vitalForce =
// get the input body part by running the M-thing
let bodyPart,remainingVitalForce =
runM bodyPartM vitalForce
// transform the body part using the function
let transformedBodyPart = f bodyPart
// return the transformed part and remaining force
(transformedBodyPart, remainingVitalForce)
// wrap the inner function in the "M" wrapper
M becomeAlive
let map f bodyPartM =
// the inner one-argument function
let becomeAlive vitalForce =
// get the input body part by running the M-thing
let bodyPart,remainingVitalForce =
runM bodyPartM vitalForce
// transform the body part using the function
let transformedBodyPart = f bodyPart
// return the transformed part and remaining force
(transformedBodyPart, remainingVitalForce)
// wrap the inner function in the "M" wrapper
M becomeAlive
let map f bodyPartM =
// the inner one-argument function
let becomeAlive vitalForce =
// get the input body part by running the M-thing
let bodyPart,remainingVitalForce =
runM bodyPartM vitalForce
// transform the body part using the function
let transformedBodyPart = f bodyPart
// return the transformed part and remaining force
(transformedBodyPart, remainingVitalForce)
// wrap the inner function in the "M" wrapper
M becomeAlive
let map f bodyPartM =
// the inner one-argument function
let becomeAlive vitalForce =
// get the input body part by running the M-thing
let bodyPart,remainingVitalForce =
runM bodyPartM vitalForce
// transform the body part using the function
let transformedBodyPart = f bodyPart
// return the transformed part and remaining force
(transformedBodyPart, remainingVitalForce)
// wrap the inner function in the "M" wrapper
M becomeAlive
let map f bodyPartM =
// the inner one-argument function
let becomeAlive vitalForce =
// get the input body part by running the M-thing
let bodyPart,remainingVitalForce =
runM bodyPartM vitalForce
// transform the body part using the function
let transformedBodyPart = f bodyPart
// return the transformed part and remaining force
(transformedBodyPart, remainingVitalForce)
// wrap the inner function in the "M" wrapper
M becomeAlive
map :
('a -> 'b ) -> // The input is a normal function.
( M<'a> -> M<'b> ) // The output is a function in the
// world of M-things.
let deadLeftBrokenArm = DeadLeftBrokenArm "Victor"
let leftBrokenArmM = makeLiveLeftBrokenArm deadLeftBrokenArm
let leftHealedArmM =
// map the healing function to the world of M-things
let healBrokenArmM = map healBrokenArm
// use it!
healBrokenArmM leftBrokenArmM
// return type is M<LiveLeftHealedArm>
// run the M<LiveLeftHealedArm> with some vital force
let liveLeftHealedArm, remainingAfterLeftArm =
runM leftHealedArmM vf
Demo – Broken Arm
let deadLeftBrokenArm = DeadLeftBrokenArm "Victor"
let leftBrokenArmM = makeLiveLeftBrokenArm deadLeftBrokenArm
let leftHealedArmM =
// map the healing function to the world of M-things
let healBrokenArmM = map healBrokenArm
// use it!
healBrokenArmM leftBrokenArmM
// return type is M<LiveLeftHealedArm>
// run the M<LiveLeftHealedArm> with some vital force
let liveLeftHealedArm, remainingAfterLeftArm =
runM leftHealedArmM vf
Demo – Broken Arm
let deadLeftBrokenArm = DeadLeftBrokenArm "Victor"
let leftBrokenArmM = makeLiveLeftBrokenArm deadLeftBrokenArm
let leftHealedArmM =
// map the healing function to the world of M-things
let healBrokenArmM = map healBrokenArm
// use it!
healBrokenArmM leftBrokenArmM
// return type is M<LiveLeftHealedArm>
// run the M<LiveLeftHealedArm> with some vital force
let liveLeftHealedArm, remainingAfterLeftArm =
runM leftHealedArmM vf
Demo – Broken Arm
// output
// liveLeftHealedArm : LiveLeftHealedArm =
// LiveLeftHealedArm ("Victor",{units = 1})
// remainingAfterLeftArm : VitalForce =
// {units = 9}
The importance of map
The "map" pattern for elevated worlds
map
ElevatedWorld
NormalWorld
a b
ElevatedWorld
Normal World
E<a> E<b>
A function in the world of normal things
where "elevated world" is
Option, List, Async, etc
The "map" pattern for elevated worlds
map
ElevatedWorld
NormalWorld
a b
ElevatedWorld
Normal World
E<a> E<b>
A function in the world of E-things
where "elevated world" is
Option, List, Async, etc
The importance of map
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
The importance of map
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
The importance of map
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
let addTwo_L inputList =
let outputList = new List()
foreach element in inputList do
let newElement = addTwo element
outputList.Add(newElement)
How not to code with lists
Let’s say you have some ints wrapped in an List, and
you want to add 2 to each element:
let addTwo x = x + 2
let addTwo_L inputList =
let outputList = new List()
foreach element in inputList do
let newElement = addTwo element
outputList.Add(newElement)
How not to code with lists
Let’s say you have some ints wrapped in an List, and
you want to add 2 to each element:
let addTwo x = x + 2
let addTwo_L inputList =
let outputList = new List()
foreach element in inputList do
let newElement = addTwo element
outputList.Add(newElement)
How not to code with lists
Let’s say you have some ints wrapped in an List, and
you want to add 2 to each element:
let addTwo x = x + 2

How not to code with lists
addTwo

World of normal values
World of Lists
How to code with lists
addTwo_L
World of normal values
World of Lists
How to code with lists
T -> U
List<T> -> List<U>
List.map
World of normal values
World of Lists
Linq.Select
How to code with lists
addTwo
addTwo_L[1;2] |>
1 |> // 3
// [3;4]
World of normal values
World of Lists
// map works with "addTwo"
let addTwo_L = List.map addTwo // List<int> -> List<int>
addTwo_L [1;2] // List<int> = [3; 4]
[1;2] |> List.map addOne // List<int> = [3; 4]
// map works with "healBrokenArm"
let healBrokenArm_L = List.map healBrokenArm
// List<LiveLeftBrokenArm> -> List<LiveLeftHealedArm>
Same applies for any generic type:
Option, Task, etc
Technique 4:
Combining two live parts
Combining two parts
Dead Lower Arm
Dead Upper Arm
Live Whole Arm
What we've got What we want
Combining two parts
Live ArmLive Lower Arm ArmSurgery
Live Whole Arm
Live Upper Arm
We have this function!
Live Arm
...and we want one of these!
How can we get it?
Combining two parts
Dead Lower Arm
We have these...
Dead Upper Arm
Live Arm
Combining two parts
Dead Lower Arm Dead Upper Arm Dead Arm
Create
ArmSurgery
Live Arm
Combining two parts
Dead Lower Arm Dead Upper Arm Dead Arm
Create

No. Only works on live arms
ArmSurgery
Create
ArmSurgery
Combining two parts
Dead Lower Arm Dead Upper Arm
Live Lower Arm Live Upper Arm Live Arm
Create
Create
ArmSurgery
No. We can't make live things
directly, only M-type things

Combining two parts
Dead Lower Arm Dead Upper Arm
Live Lower Arm Live Upper Arm Live Arm
Create
Create
ArmSurgery

Combining two parts
Dead Lower Arm Dead Upper Arm
M<LiveLowerArm> M<LiveUpperArm> M<LiveArm>
Create
No. "ArmSurgery" doesn't work
on M-type things

Create
ArmSurgeryM

Combining two parts
Dead Lower Arm Dead Upper Arm
M<LiveLowerArm> M<LiveUpperArm> M<LiveArm>
Create
We need a special "ArmSurgeryM"
that works on M-type things


Combining two parts
map2
ArmSurgeryLive Lower Arm Live Upper Arm Live Arm
ArmSurgeryMM<LiveLowerArm> M<LiveUpperArm> M<LiveArm>
World of things
World of M<_> things
Param1 -> Param2 -> Result
map2
A 2-param function in
the world of things
The "map2" pattern for M-things
A 2-param function in
the world of M<thing>s
World of things
World of M<_> things
Param1 -> Param2 -> Result
M<Param1> -> M<Param2> -> M<Result>
map2
The "map2" pattern for M-things
A 2-param function in
the world of E<thing>s
World of things
World of E<_> things
Param1 -> Param2 -> Result
E<Param1> -> E<Param2> -> E<Result>
map2
The "map2" pattern for elevated worlds
Applies to any generic type: Option, Task, etc
Technique 5:
Combining live and dead parts
Combining mismatched parts
Empty HeadDead Brain
What we've got
Live Head
What we want
Combining mismatched parts
Live HeadLive Brain HeadSurgeryEmpty Head
Combining function
alive not alive
Create
HeadSurgery
Combining mismatched parts
Dead Brain Empty Head
Live Brain Empty Head Live Head
Copy
Create
HeadSurgery
Combining mismatched parts
Dead Brain Empty Head
Live Brain Empty Head Live Head
Copy

No. We can't make live things
directly, only M-type things
Create
HeadSurgeryM

Combining mismatched parts
Dead Brain Empty Head
M<Live Brain> M<Empty Head> M<Live Head>
Create
HeadSurgeryM

Combining mismatched parts
Dead Brain Empty Head
M<Live Brain> M<Empty Head>
So what goes here?
M<Live Head>
This is not a live thing
Combining mismatched parts
return
Anything
M<Anything>
Create
HeadSurgeryM

Combining mismatched parts
Dead Brain
M<Live Brain> M<Empty Head> M<Live Head>
return
Empty Head
Create
HeadSurgeryM

Combining mismatched parts
Dead Brain
M<Live Brain> M<Empty Head> M<Live Head>
return
Empty Head
Both are M-things now
Create
HeadSurgeryM

Combining mismatched parts
Dead Brain
M<Live Brain> M<Empty Head> M<Live Head>
map2
Empty Head
Live HeadLive Brain HeadSurgeryEmpty Head
return
"return" for M-things
return
NormalWorld
a
World of M<_> things
A value in the world of normal things
"return" for M-things
return
NormalWorld
a
World of M<_> things
M<a>
A value in the world of M-things
"return" for all elevated worlds
return
NormalWorld
a
ElevatedWorld
E<a>
A value in the world of normal things
A value in the world of E-things
Technique 6:
Chaining M-generating functions
Chaining functions
Beating HeartDead Heart
What we wantWhat we've got
Chaining functions
Beating HeartLive HeartDead Heart
Creating a beating heart is
a two-step process
Chaining functions
Dead Heart M<Live Heart> Live Heart M<Beating Heart>
We have an
M-generating function
We have another
M-generating function
Dead Heart M<Live Heart>
Live Heart M<Beating Heart>


Chaining functions
Output type doesn't
match input type
Dead Heart M<Live Heart>
Live Heart M<Beating Heart>
Chaining functions

Dead Heart M<Live Heart>
M<Live Heart> M<Beating Heart>
Chaining functions
If we could change this type to
M<Live Heart>, it would work!

M<Beating Heart>M<Live Heart> makeBeatingHeartM
M<Beating Heart>Live Heart makeBeatingHeart
Chaining functions
This is what we’ve got:
an M-generating function
This is what we want:
an M-thing only function
M<Beating Heart>M<Live Heart> makeBeatingHeartM
M<Beating Heart>Live Heart makeBeatingHeart
Chaining functions
bind
"bind" converts an M-generating function
into a M-thing only function
"bind" for M-things
bind
World of M<_> things
Normal World
a
M<b>
World of M<_> things
Normal World
M<a> M<b>
an M-generating function
(diagonal)
"bind" for M-things
bind
World of M<_> things
Normal World
a
M<b>
World of M<_> things
Normal World
M<a> M<b>
a pure M-thing function
(horizontal)
Show me the code
Beating Heart and "bind"
let makeLiveHeart deadHeart =
let becomeAlive vitalForce =
// snipped
(liveHeart, remainingVitalForce)
M becomeAlive
// signature
// makeLiveHeart : DeadHeart -> M<LiveHeart>
Demo: Chaining
let makeBeatingHeart liveHeart =
let becomeAlive vitalForce =
// snipped
(beatingHeart, remainingVitalForce)
M becomeAlive
// signature
// makeBeatingHeart : LiveHeart -> M<BeatingHeart>
Demo: Chaining
let beatingHeartM =
// Convert "diagonal" to "horizontal"
let makeBeatingHeartM = bind makeBeatingHeart
Demo: Chaining
let beatingHeartM =
// Convert "diagonal" to "horizontal"
let makeBeatingHeartM = bind makeBeatingHeart
// flow the data through each function
DeadHeart "Anne" // DeadHeart
|> makeLiveHeart // output = M<LiveHeart>
|> makeBeatingHeartM // output = M<BeatingHeart>
Demo: Chaining
Q: Where did the vital force tracking go?
A: We are silently threading data
through the code.
But no globals, no mutables!
// run the M<BeatingHeart> with some vital force
let beatingHeart, remainingFromHeart =
runM beatingHeartM vf
// val beatingHeart : BeatingHeart =
// BeatingHeart (
// LiveHeart ("Anne",{units = 1}),
// {units = 1} )
//
// val remainingFromHeart : VitalForce =
// {units = 8} // TWO units used up!
Demo: Chaining
Proof that we are silently threading
the vital force through the code!
The importance of bind
"bind" for all elevated worlds
bind
Elevated World
Normal World
a
E<b>
Elevated World
Normal World
E<a> E<b>
where "elevated world" is
Option, List, Async, etc
"bind" for all elevated worlds
bind
Elevated World
Normal World
a
E<b>
Elevated World
Normal World
E<a> E<b>
where "elevated world" is
Option, List, Async, etc
The importance of bind
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
"Diagonal" functions
The importance of bind
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
Bind
"SelectMany“ in C#
The importance of bind
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
Bind
The importance of bind
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
Bind
The importance of bind
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
“Horizontal" functions
Technique 7:
Lifting arbitrary functions
Making "map3", "map4", "map5"
on the fly
type LiveBody = {
leftLeg: LiveLeftLeg
rightLeg : LiveLeftLeg
leftArm : LiveLeftHealedArm
rightArm : LiveRightArm
head : LiveHead
heart : BeatingHeart }
Defining the whole body
val createBody :
leftLeg :LiveLeftLeg ->
rightLeg :LiveLeftLeg ->
leftArm :LiveLeftHealedArm ->
rightArm :LiveRightArm ->
head :LiveHead ->
beatingHeart :BeatingHeart ->
LiveBody // final result
Creating the whole body
Do we need a "mapSix" function?
Introducing "apply"
apply
World of M<_> things
M<(a->b)>
World of M<_> things
Introducing "apply"
apply
World of M<_> things
M<(a->b)>
World of M<_> things
M<a> M<b>
Introducing "apply"
apply
World of M<_> things
M<(a->b)>
World of M<_> things
M<a> M<b>
apply
M<(a->b->c)> M<a> M<b->c>
Introducing "apply"
apply
World of M<_> things
M<(a->b)>
World of M<_> things
M<a> M<b>
apply
M<(a->b->c)> M<a> M<b->c>
apply
M<(a->b->c->d)> M<a> M<b->c->d>
Using "apply" to make "map3"
apply
M<(a->b->c->d)> M<a> M<b->c->d>
Using "apply" to make "map3"
apply
M<(b->c->d)> M<b> M<c->d>
apply
M<(a->b->c->d)> M<a> M<b->c->d>
Using "apply" to make "map3"
apply
M<(b->c->d)> M<b> M<c->d>
M<c->d>
apply
M<c> M<d>
apply
M<(a->b->c->d)> M<a> M<b->c->d>
Using "apply" to make "map3"
a->b->c->Result a b c Result
Using "apply" to make "map3"
M<(a->b->c->d)>
a->b->c->Result a b c Result
return
Using "apply" to make "map3"
apply
M<(a->b->c->d)> M<a>
a->b->c->Result a b c Result
return create
Using "apply" to make "map3"
apply
M<(a->b->c->d)> M<a> M<b>
a->b->c->Result a b c Result
return create create
apply
Using "apply" to make "map3"
apply
M<(a->b->c->d)> M<a> M<b> M<c>
a->b->c->Result a b c Result
return create create create
apply apply
Using "apply" to make "map3"
apply
M<(a->b->c->d)> M<a> M<b> M<c> M<Result>
a->b->c->Result a b c Result
return create create create
apply apply
Show me the code
Whole body and "apply"
// create the body in the "normal" world
let createBody leftLeg rightLeg leftArm
rightArm head heart =
{
leftLeg = leftLeg
rightLeg = rightLeg
leftArm = leftArm
rightArm = rightArm
head = head
heart = heart
}
Demo: Whole body
// <*> means "apply"
let bodyM =
returnM createBody
<*> leftLegM
<*> rightLegM
<*> leftHealedArmM
<*> rightArmM
<*> headM
<*> beatingHeartM
// output is M<LiveBody>
Demo: Whole body
M-Things from
earlier
Output is still a potential thing.
We're "programming"!
// Lightning strikes! It's alive!
let liveBody, remainingFromBody = runM bodyM vf
// val liveBody : LiveBody =
// {leftLeg = LiveLeftLeg ("Boris",{units = 1})
// rightLeg = LiveLeftLeg ("Boris",{units = 1})
// leftArm = LiveLeftArm ("Victor",{units = 1})
// rightArm = {lowerArm = LiveRightLowerArm
// ("Tom",{units = 1})
// upperArm = LiveRightUpperArm
// ("Jerry",{units = 1}) }
// head = {brain = LiveBrain
// ("Abby Normal",{units = 1})
// emptyHead = EmptyHead "Yorick"}
// heart = BeatingHeart (
// LiveHeart ("Anne",{units = 1}),
// {units = 1})}
// val remainingFromBody : VitalForce = {units = 2}
Demo: Whole body
The state is automatically kept up-to-date
Is your brain hurting now?
Do we still have two problems?
Live part B
Vital force
Become alive B!
Remaining vital force
Dead part B
Live part A
Vital force
Become alive A!
Remaining vital force
Dead part A
Connect the force between two
steps using "bind" or "apply"
Live part B
Vital force
Become alive B!
Remaining vital force
Dead part B
Live part A
Vital force
Become alive A!
Remaining vital force
Dead part A
Combine two outputs
using "map2"
A FunctionalToolbox
map
return
bind
map2
apply
The FunctionalToolbox
• "map"
– Lifts functions into the elevated world
• "return"
– Lifts values into the elevated world
• "apply"
– Lets you combine elevated values
– "map2" is a just a specialized "apply“
• "bind"
– Converts “diagonal” functions into horizontal ones
The FunctionalToolbox
• "map"
– (with a sensible implementation) is a Functor
• "return" and "apply"
– (with a sensible implementation) is an Applicative
• "return" and "bind"
– (with a sensible implementation) is a Monad
The State monad
The state is threaded through the
code "invisibly"
let beatingHeartM =
DeadHeart "Anne"
|> makeLiveHeart
|> makeBeatingHeartM
// TWO units of force used up
State monad
Where is the "vital force"
tracking variable?
let bodyM =
returnM createBody
<*> leftLegM
<*> rightLegM
<*> leftHealedArmM
<*> rightArmM
<*> headM
<*> beatingHeartM
// EIGHT units of force used up
State monad
Where is the "vital
force" variable?
We are silently threading the vital
force through the code...
...which allows us to focus on the design instead
Using Dr Frankenfunctor's
techniques in the real world
Is this too academic?
Too abstract to be useful?
Scenario: Update user information
• Input is {userId, name, email}
• Step 1:Validate input
– Could fail if name is blank, etc
• Step 2: Canonicalize input
– Trim blanks, lowercase email, etc
• Step 3: Fetch existing record from db
– Could fail if record is missing
• Step 4: Update record in db
Validate
Generates a possible error
Validate Canonicalize
Generates a possible error Always succeeds
Validate Canonicalize DbFetch
Generates a possible error Generates a possible errorAlways succeeds
Validate Canonicalize DbFetch DbUpdate
Generates a possible error Generates a possible errorAlways succeeds Doesn't return
How can we glue these
mismatched functions together?
World of normal things
"lift" from this world
World of two-track things
to this world
World of normal things
World of two-track things
bindmap apply
map
Converting everything to two-track
bind
map
Converting everything to two-track
bind
map
tee map
Converting everything to two-track
Validate Canonicalize DbFetch DbUpdate
Now we *can* glue
these together easily!
map bind tee, then map
Summary
• We've seen a toolkit of useful techniques
– Don’t expect to understand them all straight away.
• How to wrap a function into a type
– A.k.a. a "computation" or "effect“
• How to use "map", "apply" and "bind"
– Monads are not that scary
– You can work with effects before running them!
• How to thread state "invisibly" through code
– Without using any globals or mutables!
Thanks!
@ScottWlaschin
fsharpforfunandprofit.com/monadster
Contact me
Slides and video here
Let us know if you
need help with F#

More Related Content

What's hot

Enterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeEnterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeScott Wlaschin
 
Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Scott Wlaschin
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionKent Huang
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modelingMario Fusco
 
Clean code - DSC DYPCOE
Clean code - DSC DYPCOEClean code - DSC DYPCOE
Clean code - DSC DYPCOEPatil Shreyas
 
The Power Of Composition (DotNext 2019)
The Power Of Composition (DotNext 2019)The Power Of Composition (DotNext 2019)
The Power Of Composition (DotNext 2019)Scott Wlaschin
 
7 rules of simple and maintainable code
7 rules of simple and maintainable code7 rules of simple and maintainable code
7 rules of simple and maintainable codeGeshan Manandhar
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsPhilip Schwarz
 
The Functional Programmer's Toolkit (NDC London 2019)
The Functional Programmer's Toolkit (NDC London 2019)The Functional Programmer's Toolkit (NDC London 2019)
The Functional Programmer's Toolkit (NDC London 2019)Scott Wlaschin
 
Functional solid
Functional solidFunctional solid
Functional solidMatt Stine
 
An introduction to property based testing
An introduction to property based testingAn introduction to property based testing
An introduction to property based testingScott Wlaschin
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced JavascriptAdieu
 
Thirteen ways of looking at a turtle
Thirteen ways of looking at a turtleThirteen ways of looking at a turtle
Thirteen ways of looking at a turtleScott Wlaschin
 
Multiple Inheritance
Multiple InheritanceMultiple Inheritance
Multiple InheritanceBhavyaJain137
 
A Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOA Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOJorge Vásquez
 

What's hot (20)

Clean code
Clean codeClean code
Clean code
 
Enterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeEnterprise Tic-Tac-Toe
Enterprise Tic-Tac-Toe
 
Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)
 
Clean Code: Chapter 3 Function
Clean Code: Chapter 3 FunctionClean Code: Chapter 3 Function
Clean Code: Chapter 3 Function
 
From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
 
Clean code
Clean codeClean code
Clean code
 
Clean code - DSC DYPCOE
Clean code - DSC DYPCOEClean code - DSC DYPCOE
Clean code - DSC DYPCOE
 
The Power Of Composition (DotNext 2019)
The Power Of Composition (DotNext 2019)The Power Of Composition (DotNext 2019)
The Power Of Composition (DotNext 2019)
 
7 rules of simple and maintainable code
7 rules of simple and maintainable code7 rules of simple and maintainable code
7 rules of simple and maintainable code
 
Clean code
Clean codeClean code
Clean code
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
 
The Functional Programmer's Toolkit (NDC London 2019)
The Functional Programmer's Toolkit (NDC London 2019)The Functional Programmer's Toolkit (NDC London 2019)
The Functional Programmer's Toolkit (NDC London 2019)
 
Clean coding-practices
Clean coding-practicesClean coding-practices
Clean coding-practices
 
Functional solid
Functional solidFunctional solid
Functional solid
 
An introduction to property based testing
An introduction to property based testingAn introduction to property based testing
An introduction to property based testing
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced Javascript
 
Thirteen ways of looking at a turtle
Thirteen ways of looking at a turtleThirteen ways of looking at a turtle
Thirteen ways of looking at a turtle
 
Haskell study 6
Haskell study 6Haskell study 6
Haskell study 6
 
Multiple Inheritance
Multiple InheritanceMultiple Inheritance
Multiple Inheritance
 
A Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIOA Prelude of Purity: Scaling Back ZIO
A Prelude of Purity: Scaling Back ZIO
 

More from Scott Wlaschin

Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Scott Wlaschin
 
Building confidence in concurrent code with a model checker: TLA+ for program...
Building confidence in concurrent code with a model checker: TLA+ for program...Building confidence in concurrent code with a model checker: TLA+ for program...
Building confidence in concurrent code with a model checker: TLA+ for program...Scott Wlaschin
 
Domain Modeling with FP (DDD Europe 2020)
Domain Modeling with FP (DDD Europe 2020)Domain Modeling with FP (DDD Europe 2020)
Domain Modeling with FP (DDD Europe 2020)Scott Wlaschin
 
Reinventing the Transaction Script (NDC London 2020)
Reinventing the Transaction Script (NDC London 2020)Reinventing the Transaction Script (NDC London 2020)
Reinventing the Transaction Script (NDC London 2020)Scott Wlaschin
 
Domain Modeling Made Functional (KanDDDinsky 2019)
Domain Modeling Made Functional (KanDDDinsky 2019)Domain Modeling Made Functional (KanDDDinsky 2019)
Domain Modeling Made Functional (KanDDDinsky 2019)Scott Wlaschin
 
Four Languages From Forty Years Ago (NewCrafts 2019)
Four Languages From Forty Years Ago (NewCrafts 2019)Four Languages From Forty Years Ago (NewCrafts 2019)
Four Languages From Forty Years Ago (NewCrafts 2019)Scott Wlaschin
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Scott Wlaschin
 
Four Languages From Forty Years Ago
Four Languages From Forty Years AgoFour Languages From Forty Years Ago
Four Languages From Forty Years AgoScott Wlaschin
 
The Power of Composition
The Power of CompositionThe Power of Composition
The Power of CompositionScott Wlaschin
 
Designing with capabilities (DDD-EU 2017)
Designing with capabilities (DDD-EU 2017)Designing with capabilities (DDD-EU 2017)
Designing with capabilities (DDD-EU 2017)Scott Wlaschin
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Scott Wlaschin
 
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014Scott Wlaschin
 

More from Scott Wlaschin (16)

Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)Domain Modeling Made Functional (DevTernity 2022)
Domain Modeling Made Functional (DevTernity 2022)
 
Building confidence in concurrent code with a model checker: TLA+ for program...
Building confidence in concurrent code with a model checker: TLA+ for program...Building confidence in concurrent code with a model checker: TLA+ for program...
Building confidence in concurrent code with a model checker: TLA+ for program...
 
Domain Modeling with FP (DDD Europe 2020)
Domain Modeling with FP (DDD Europe 2020)Domain Modeling with FP (DDD Europe 2020)
Domain Modeling with FP (DDD Europe 2020)
 
Reinventing the Transaction Script (NDC London 2020)
Reinventing the Transaction Script (NDC London 2020)Reinventing the Transaction Script (NDC London 2020)
Reinventing the Transaction Script (NDC London 2020)
 
Domain Modeling Made Functional (KanDDDinsky 2019)
Domain Modeling Made Functional (KanDDDinsky 2019)Domain Modeling Made Functional (KanDDDinsky 2019)
Domain Modeling Made Functional (KanDDDinsky 2019)
 
Four Languages From Forty Years Ago (NewCrafts 2019)
Four Languages From Forty Years Ago (NewCrafts 2019)Four Languages From Forty Years Ago (NewCrafts 2019)
Four Languages From Forty Years Ago (NewCrafts 2019)
 
Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)Functional Design Patterns (DevTernity 2018)
Functional Design Patterns (DevTernity 2018)
 
Four Languages From Forty Years Ago
Four Languages From Forty Years AgoFour Languages From Forty Years Ago
Four Languages From Forty Years Ago
 
The Power of Composition
The Power of CompositionThe Power of Composition
The Power of Composition
 
F# for C# Programmers
F# for C# ProgrammersF# for C# Programmers
F# for C# Programmers
 
Designing with capabilities (DDD-EU 2017)
Designing with capabilities (DDD-EU 2017)Designing with capabilities (DDD-EU 2017)
Designing with capabilities (DDD-EU 2017)
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)
 
Swift vs. Language X
Swift vs. Language XSwift vs. Language X
Swift vs. Language X
 
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
 
Doge-driven design
Doge-driven designDoge-driven design
Doge-driven design
 
The Theory of Chains
The Theory of ChainsThe Theory of Chains
The Theory of Chains
 

Recently uploaded

How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfhans926745
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdfChristopherTHyatt
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 

Recently uploaded (20)

How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 

Dr Frankenfunctor and the Monadster

  • 1. Dr Frankenfunctor and the Monadster @ScottWlaschin fsharpforfunandprofit.com/monadster
  • 2. Warning This talk contains: – gruesome topics – strained analogies – discussion of monads Not suitable for sensitive people (seriously)
  • 7. function A and B Easy!
  • 8. ... But here is a challenge for function composition
  • 9. function AInput Output function BInput Output 1 Output 2 function C Input 1 Output 1 Output 2Input 2 function D Input 1 Output Input 2
  • 10. function AInput Output function BInput Output 1 Output 2 function D Input 1 Output Input 2 How to compose?
  • 11. function AInput Output function BInput Output 1 Output 2 function D Input 1 Output Input 2 How to compose?
  • 13. The spread of the monad • 1990 ACM Conference on LISP and Functional Programming First monad in captivity
  • 14. The terrible events at the 1990 ACM Conference on LISP and Functional Programming
  • 15. The spread of the monad • 1990 ACM Conference on LISP and Functional Programming • 1991 Eugenio Moggi, "Notions of computation and monads" • 1992 PhilipWadler, "Monads for Functional Programming" • 1999 Noel Winstanley, "What the hell are Monads?" • 2004 Greg Buchholz, "Monads in Perl" • 2005 Eric Kow, "Of monads and space suits" • 2006 Eric Kow, Monads as nuclear waste containers • 2009 James Iry, "A monad is just a monoid in the category of endofunctors, what's the problem?" • It’s everywhere now
  • 16. The spread of the monad • 1990 ACM Conference on LISP and Functional Programming • 1991 Eugenio Moggi, "Notions of computation and monads" • 1992 PhilipWadler, "Monads for Functional Programming" • 1999 Noel Winstanley, "What the hell are Monads?" • 2004 Greg Buchholz, "Monads in Perl" • 2005 Eric Kow, "Of monads and space suits" • 2006 Eric Kow, Monads as nuclear waste containers • 2009 James Iry, "A monad is just a monoid in the category of endofunctors, what's the problem?" • It’s everywhere now No wonder people think monads are dangerous
  • 17. The secret history of the monad • 1816 Dr Frankenfunctor creates the Monadster • 1990 ACM Conference on LISP and Functional Programming • 1991 Eugenio Moggi, "Notions of computation and monads" • 1992 PhilipWadler, "Monads for Functional Programming" • 1999 Noel Winstanley, "What the hell are Monads?" • 2004 Greg Buchholz, "Monads in Perl" • 2005 Eric Kow, "Of monads and space suits" • 2006 Eric Kow, Monads as nuclear waste containers • 2009 James Iry, "A monad is just a monoid in the category of endofunctors, what's the problem?" • And 100's more The topic of this talk
  • 18. The story of the Monadster
  • 19. The creature was built from body parts of various shapes
  • 20. The various parts were assembled into a whole
  • 21. The body was animated in a single instant, using a bolt of lightning to create the vital force.
  • 22. ...The Monadster The “mark of the lambda”
  • 23. But how was it done? I have devoted many years of research into this matter...
  • 24. At last, I can reveal the secret techniques of Dr Frankenfunctor! Warning: These are powerful techniques and can be used for good or evil... I know of a young, innocent developer who was traumatized for life.
  • 25. Dr Frankenfunctor's toolbox 1. Modelling with pure functions 2. Wrapping a function in a type 3. Transforming parts into other parts 4. Combining two parts into one 5. Combining live and dead parts 6. Chaining “part-creating” functions together 7. A general way of combining any number of parts I don’t expect you to remember all this! Goal is just to demystify and give an overview
  • 26. Technique 1: Modelling with pure functions
  • 27. Become alive! Vital force Dead part Live part Don't try this at home
  • 28. Live body part Vital force Become alive! Remaining vital force Dead body part Two inputs
  • 29. Live body part Vital force Become alive! Remaining vital force Dead body part Two outputs
  • 30. Live body part Vital force Become alive! Remaining vital force Dead body part Less vital force available afterwards
  • 31. Live body part Vital force Become alive! Remaining vital force Dead body part No globals, no mutation!
  • 32. But now you have two problems...
  • 33. Live part B Vital force Become alive B! Remaining vital force Dead part B Live part A Vital force Become alive A! Remaining vital force Dead part A How to connect the force between two steps?
  • 34. Live part B Vital force Become alive B! Remaining vital force Dead part B Live part A Vital force Become alive A! Remaining vital force Dead part A How to combine the two outputs?
  • 35. Technique 2: Wrapping the "Become Alive" function Also, introducing schönfinkelling
  • 38. Haskell Curry gave his name to currying
  • 39. Input A Uncurried Function Input B Output C Curried Function Input A Intermediate Function Output CInput B What is currying? after currying Currying means that *every* function has one input
  • 40. // naming a lambda Func<int,int> add1 = (y => 1 + y) // using it var three = add1(2) Currying examples
  • 41. // naming a lambda let add1 = (fun y -> 1 + y) // using it let three = add1 2 Currying examples
  • 42. // returning a lambda with baked in "x" let add x = (fun y -> x + y) // creating an intermediate function let add1 = add 1 // (fun y -> 1 + y) // using it let three = add1 2 Currying examples
  • 43. // "inlining" the intermediate function let three = (add 1) 2 // returning a lambda with baked in "x" let add x = (fun y -> x + y) Currying examples
  • 44. // removing the parens let three = add 1 2 Currying examples // returning a lambda with baked in "x" let add x = (fun y -> x + y)
  • 45. Live part A Vital force Become alive! Remaining vital force Dead part A Currying "become alive!"
  • 46. Become alive! Dead part A Vital force Live part A Currying "become alive!"
  • 47. Become alive! Dead part A Vital force M<Live Part A> Live part A Wrapping the function "M" is for "Monadster"
  • 48. Become alive! Dead part A Vital force M<Live Part A> Live part A Wrapping the function
  • 49. Dead part A M<Live Part A> Create step in recipe Wrapping the function An "M-making" function Remember -- this is *not* a live part , it's a "potential" live part
  • 50. M<Live Part A> Run Live part A Remaining vital force Running the function Vital force
  • 51. M<Live Part A> Run Live part A Remaining vital force Running the function Vital force Become alive! Vital force Live part A M<Live Part A>
  • 52. Show me the code Left Leg
  • 53. let makeLiveThingM deadThing = // the inner one-argument function let becomeAlive vitalForceInput = ... do stuff ... return two outputs // wrap the inner function in the "M" wrapper M becomeAlive Creating M-things
  • 54. let makeLiveThingM deadThing = // get essence of dead thing let essence = getEssenceOfDeadThing deadThing // the inner one-argument function let becomeAlive vitalForceInput = // get a unit of vital force let unitOfForce, remainingForce = getVitalForce vitalForce // create a live thing let liveThing = new LiveThing(essence, unitOfForce) // return the live thing and remaining force (liveThing, remainingVitalForce) // return a pair // wrap the inner function in the "M" wrapper M becomeAlive Creating M-things
  • 55. let makeLiveThingM deadThing = // get essence of dead thing let essence = getEssenceOfDeadThing deadThing // the inner one-argument function let becomeAlive vitalForceInput = // get a unit of vital force let unitOfForce, remainingForce = getVitalForce vitalForce // create a live thing let liveThing = new LiveThing(essence, unitOfForce) // return the live thing and remaining force (liveThing, remainingVitalForce) // return a pair // wrap the inner function in the "M" wrapper M becomeAlive Creating M-things
  • 56. let makeLiveThingM deadThing = // get essence of dead thing let essence = getEssenceOfDeadThing deadThing // the inner one-argument function let becomeAlive vitalForceInput = // get a unit of vital force let unitOfForce, remainingForce = getVitalForce vitalForce // create a live thing let liveThing = new LiveThing(essence, unitOfForce) // return the live thing and remaining force (liveThing, remainingVitalForce) // return a pair // wrap the inner function in the "M" wrapper M becomeAlive Creating M-things
  • 57. let makeLiveThingM deadThing = // get essence of dead thing let essence = getEssenceOfDeadThing deadThing // the inner one-argument function let becomeAlive vitalForceInput = // get a unit of vital force let unitOfForce, remainingForce = getVitalForce vitalForce // create a live thing let liveThing = new LiveThing(essence, unitOfForce) // return the live thing and remaining force (liveThing, remainingVitalForce) // return a pair // wrap the inner function in the "M" wrapper M becomeAlive Creating M-things
  • 58. let makeLiveThingM deadThing = // get essence of dead thing let essence = getEssenceOfDeadThing deadThing // the inner one-argument function let becomeAlive vitalForceInput = // get a unit of vital force let unitOfForce, remainingForce = getVitalForce vitalForce // create a live thing let liveThing = new LiveThing(essence, unitOfForce) // return the live thing and remaining force (liveThing, remainingVitalForce) // return a pair // wrap the inner function in the "M" wrapper M becomeAlive Creating M-things
  • 59. let makeLiveThingM deadThing = // get essence of dead thing let essence = getEssenceOfDeadThing deadThing // the inner one-argument function let becomeAlive vitalForceInput = // get a unit of vital force let unitOfForce, remainingForce = getVitalForce vitalForce // create a live thing let liveThing = new LiveThing(essence, unitOfForce) // return the live thing and remaining force (liveThing, remainingVitalForce) // return a pair // wrap the inner function in the "M" wrapper M becomeAlive Creating M-things makeLiveThingM : DeadThing -> M<LiveThing>
  • 60. // create DeadLeftLeg let deadLeftLeg = DeadLeftLeg "Boris" // create a M<LiveLeftLeg> let leftLegM = makeLiveLeftLegM deadLeftLeg // potential leg only! // now pretend that vital force is available let vf = {units = 10} // make a real left leg by running leftLegM let liveLeftLeg, remainingForce = runM leftLegM vf // output: // liveLeftLeg : LiveLeftLeg = // LiveLeftLeg ("Boris",{units = 1}) // remainingForce : VitalForce = {units = 9} Demo – Left Leg
  • 62. A Broken Arm Dead Broken Arm What we've got Live Healed Arm What we want
  • 63. Healing a broken arm Live Healed ArmLive Broken Arm HealBrokenArm We have this function!
  • 64. Live Healed Arm ...But we want one of these! How can we get it? Healing a broken arm Dead Broken Arm We have one of these...
  • 65. Create Dead Broken Arm Dead Healed Arm Live Healed Arm Healing a broken arm HealBrokenArm
  • 66. Create Dead Broken Arm Dead Healed Arm Live Healed Arm  No. We can only heal live arms Healing a broken arm HealBrokenArm
  • 67. Dead Broken Arm Live Healed ArmLive Broken Arm Create HealBrokenArm Healing a broken arm
  • 68. Dead Broken Arm Live Healed ArmLive Broken Arm Create HealBrokenArm No. We can't create live things directly, only M-type things  Healing a broken arm 
  • 69. Dead Broken Arm M<Live Healed Arm>M<Live Broken Arm> Create HealBrokenArm Healing a broken arm
  • 70. Dead Broken Arm M<Live Healed Arm>  M<Live Broken Arm> Create HealBrokenArm No. "HealBrokenArm" doesn't work on M-type things  Healing a broken arm
  • 71. Dead Broken Arm M<Live Healed Arm>M<Live Broken Arm> Create HealBrokenArmM We need a special "HealBrokenArmM" that works on M-type things   Where can we get it from? Healing a broken arm
  • 72. Live Healed ArmLive Broken Arm HealBrokenArm Healing a broken arm M<Live Healed Arm>M<Live Broken Arm> HealBrokenArmM This is what we’ve got This is what we want
  • 73. Live Healed ArmLive Broken Arm HealBrokenArm Healing a broken arm M<Live Healed Arm>M<Live Broken Arm> HealBrokenArmM map
  • 74. "map" is generic for M-things NormalWorld a b
  • 75. "map" is generic for M-things NormalWorld a b map
  • 76. "map" is generic for M-things NormalWorld a b map World of M<_> things M<a> M<b> A function in the world of M-things “lifting”
  • 77. Show me the code Broken Arm and "map"
  • 78. let map f bodyPartM = // the inner one-argument function let becomeAlive vitalForce = // get the input body part by running the M-thing let bodyPart,remainingVitalForce = runM bodyPartM vitalForce // transform the body part using the function let transformedBodyPart = f bodyPart // return the transformed part and remaining force (transformedBodyPart, remainingVitalForce) // wrap the inner function in the "M" wrapper M becomeAlive Transformation function M-thing to transform
  • 79. let map f bodyPartM = // the inner one-argument function let becomeAlive vitalForce = // get the input body part by running the M-thing let bodyPart,remainingVitalForce = runM bodyPartM vitalForce // transform the body part using the function let transformedBodyPart = f bodyPart // return the transformed part and remaining force (transformedBodyPart, remainingVitalForce) // wrap the inner function in the "M" wrapper M becomeAlive
  • 80. let map f bodyPartM = // the inner one-argument function let becomeAlive vitalForce = // get the input body part by running the M-thing let bodyPart,remainingVitalForce = runM bodyPartM vitalForce // transform the body part using the function let transformedBodyPart = f bodyPart // return the transformed part and remaining force (transformedBodyPart, remainingVitalForce) // wrap the inner function in the "M" wrapper M becomeAlive
  • 81. let map f bodyPartM = // the inner one-argument function let becomeAlive vitalForce = // get the input body part by running the M-thing let bodyPart,remainingVitalForce = runM bodyPartM vitalForce // transform the body part using the function let transformedBodyPart = f bodyPart // return the transformed part and remaining force (transformedBodyPart, remainingVitalForce) // wrap the inner function in the "M" wrapper M becomeAlive
  • 82. let map f bodyPartM = // the inner one-argument function let becomeAlive vitalForce = // get the input body part by running the M-thing let bodyPart,remainingVitalForce = runM bodyPartM vitalForce // transform the body part using the function let transformedBodyPart = f bodyPart // return the transformed part and remaining force (transformedBodyPart, remainingVitalForce) // wrap the inner function in the "M" wrapper M becomeAlive
  • 83. let map f bodyPartM = // the inner one-argument function let becomeAlive vitalForce = // get the input body part by running the M-thing let bodyPart,remainingVitalForce = runM bodyPartM vitalForce // transform the body part using the function let transformedBodyPart = f bodyPart // return the transformed part and remaining force (transformedBodyPart, remainingVitalForce) // wrap the inner function in the "M" wrapper M becomeAlive map : ('a -> 'b ) -> // The input is a normal function. ( M<'a> -> M<'b> ) // The output is a function in the // world of M-things.
  • 84. let deadLeftBrokenArm = DeadLeftBrokenArm "Victor" let leftBrokenArmM = makeLiveLeftBrokenArm deadLeftBrokenArm let leftHealedArmM = // map the healing function to the world of M-things let healBrokenArmM = map healBrokenArm // use it! healBrokenArmM leftBrokenArmM // return type is M<LiveLeftHealedArm> // run the M<LiveLeftHealedArm> with some vital force let liveLeftHealedArm, remainingAfterLeftArm = runM leftHealedArmM vf Demo – Broken Arm
  • 85. let deadLeftBrokenArm = DeadLeftBrokenArm "Victor" let leftBrokenArmM = makeLiveLeftBrokenArm deadLeftBrokenArm let leftHealedArmM = // map the healing function to the world of M-things let healBrokenArmM = map healBrokenArm // use it! healBrokenArmM leftBrokenArmM // return type is M<LiveLeftHealedArm> // run the M<LiveLeftHealedArm> with some vital force let liveLeftHealedArm, remainingAfterLeftArm = runM leftHealedArmM vf Demo – Broken Arm
  • 86. let deadLeftBrokenArm = DeadLeftBrokenArm "Victor" let leftBrokenArmM = makeLiveLeftBrokenArm deadLeftBrokenArm let leftHealedArmM = // map the healing function to the world of M-things let healBrokenArmM = map healBrokenArm // use it! healBrokenArmM leftBrokenArmM // return type is M<LiveLeftHealedArm> // run the M<LiveLeftHealedArm> with some vital force let liveLeftHealedArm, remainingAfterLeftArm = runM leftHealedArmM vf Demo – Broken Arm // output // liveLeftHealedArm : LiveLeftHealedArm = // LiveLeftHealedArm ("Victor",{units = 1}) // remainingAfterLeftArm : VitalForce = // {units = 9}
  • 88. The "map" pattern for elevated worlds map ElevatedWorld NormalWorld a b ElevatedWorld Normal World E<a> E<b> A function in the world of normal things where "elevated world" is Option, List, Async, etc
  • 89. The "map" pattern for elevated worlds map ElevatedWorld NormalWorld a b ElevatedWorld Normal World E<a> E<b> A function in the world of E-things where "elevated world" is Option, List, Async, etc
  • 90. The importance of map World of normal values int string bool World of Lists List<int> List<string> List<bool>
  • 91. The importance of map World of normal values int string bool World of Lists List<int> List<string> List<bool>
  • 92. The importance of map World of normal values int string bool World of Lists List<int> List<string> List<bool>
  • 93. let addTwo_L inputList = let outputList = new List() foreach element in inputList do let newElement = addTwo element outputList.Add(newElement) How not to code with lists Let’s say you have some ints wrapped in an List, and you want to add 2 to each element: let addTwo x = x + 2
  • 94. let addTwo_L inputList = let outputList = new List() foreach element in inputList do let newElement = addTwo element outputList.Add(newElement) How not to code with lists Let’s say you have some ints wrapped in an List, and you want to add 2 to each element: let addTwo x = x + 2
  • 95. let addTwo_L inputList = let outputList = new List() foreach element in inputList do let newElement = addTwo element outputList.Add(newElement) How not to code with lists Let’s say you have some ints wrapped in an List, and you want to add 2 to each element: let addTwo x = x + 2 
  • 96. How not to code with lists addTwo  World of normal values World of Lists
  • 97. How to code with lists addTwo_L World of normal values World of Lists
  • 98. How to code with lists T -> U List<T> -> List<U> List.map World of normal values World of Lists Linq.Select
  • 99. How to code with lists addTwo addTwo_L[1;2] |> 1 |> // 3 // [3;4] World of normal values World of Lists
  • 100. // map works with "addTwo" let addTwo_L = List.map addTwo // List<int> -> List<int> addTwo_L [1;2] // List<int> = [3; 4] [1;2] |> List.map addOne // List<int> = [3; 4] // map works with "healBrokenArm" let healBrokenArm_L = List.map healBrokenArm // List<LiveLeftBrokenArm> -> List<LiveLeftHealedArm> Same applies for any generic type: Option, Task, etc
  • 102. Combining two parts Dead Lower Arm Dead Upper Arm Live Whole Arm What we've got What we want
  • 103. Combining two parts Live ArmLive Lower Arm ArmSurgery Live Whole Arm Live Upper Arm We have this function!
  • 104. Live Arm ...and we want one of these! How can we get it? Combining two parts Dead Lower Arm We have these... Dead Upper Arm
  • 105. Live Arm Combining two parts Dead Lower Arm Dead Upper Arm Dead Arm Create ArmSurgery
  • 106. Live Arm Combining two parts Dead Lower Arm Dead Upper Arm Dead Arm Create  No. Only works on live arms ArmSurgery
  • 107. Create ArmSurgery Combining two parts Dead Lower Arm Dead Upper Arm Live Lower Arm Live Upper Arm Live Arm Create
  • 108. Create ArmSurgery No. We can't make live things directly, only M-type things  Combining two parts Dead Lower Arm Dead Upper Arm Live Lower Arm Live Upper Arm Live Arm Create
  • 109. Create ArmSurgery  Combining two parts Dead Lower Arm Dead Upper Arm M<LiveLowerArm> M<LiveUpperArm> M<LiveArm> Create No. "ArmSurgery" doesn't work on M-type things 
  • 110. Create ArmSurgeryM  Combining two parts Dead Lower Arm Dead Upper Arm M<LiveLowerArm> M<LiveUpperArm> M<LiveArm> Create We need a special "ArmSurgeryM" that works on M-type things  
  • 111. Combining two parts map2 ArmSurgeryLive Lower Arm Live Upper Arm Live Arm ArmSurgeryMM<LiveLowerArm> M<LiveUpperArm> M<LiveArm>
  • 112. World of things World of M<_> things Param1 -> Param2 -> Result map2 A 2-param function in the world of things The "map2" pattern for M-things
  • 113. A 2-param function in the world of M<thing>s World of things World of M<_> things Param1 -> Param2 -> Result M<Param1> -> M<Param2> -> M<Result> map2 The "map2" pattern for M-things
  • 114. A 2-param function in the world of E<thing>s World of things World of E<_> things Param1 -> Param2 -> Result E<Param1> -> E<Param2> -> E<Result> map2 The "map2" pattern for elevated worlds Applies to any generic type: Option, Task, etc
  • 115. Technique 5: Combining live and dead parts
  • 116. Combining mismatched parts Empty HeadDead Brain What we've got Live Head What we want
  • 117. Combining mismatched parts Live HeadLive Brain HeadSurgeryEmpty Head Combining function alive not alive
  • 118. Create HeadSurgery Combining mismatched parts Dead Brain Empty Head Live Brain Empty Head Live Head Copy
  • 119. Create HeadSurgery Combining mismatched parts Dead Brain Empty Head Live Brain Empty Head Live Head Copy  No. We can't make live things directly, only M-type things
  • 120. Create HeadSurgeryM  Combining mismatched parts Dead Brain Empty Head M<Live Brain> M<Empty Head> M<Live Head>
  • 121. Create HeadSurgeryM  Combining mismatched parts Dead Brain Empty Head M<Live Brain> M<Empty Head> So what goes here? M<Live Head> This is not a live thing
  • 123. Create HeadSurgeryM  Combining mismatched parts Dead Brain M<Live Brain> M<Empty Head> M<Live Head> return Empty Head
  • 124. Create HeadSurgeryM  Combining mismatched parts Dead Brain M<Live Brain> M<Empty Head> M<Live Head> return Empty Head Both are M-things now
  • 125. Create HeadSurgeryM  Combining mismatched parts Dead Brain M<Live Brain> M<Empty Head> M<Live Head> map2 Empty Head Live HeadLive Brain HeadSurgeryEmpty Head return
  • 126. "return" for M-things return NormalWorld a World of M<_> things A value in the world of normal things
  • 127. "return" for M-things return NormalWorld a World of M<_> things M<a> A value in the world of M-things
  • 128. "return" for all elevated worlds return NormalWorld a ElevatedWorld E<a> A value in the world of normal things A value in the world of E-things
  • 130. Chaining functions Beating HeartDead Heart What we wantWhat we've got
  • 131. Chaining functions Beating HeartLive HeartDead Heart Creating a beating heart is a two-step process
  • 132. Chaining functions Dead Heart M<Live Heart> Live Heart M<Beating Heart> We have an M-generating function We have another M-generating function
  • 133. Dead Heart M<Live Heart> Live Heart M<Beating Heart>   Chaining functions Output type doesn't match input type
  • 134. Dead Heart M<Live Heart> Live Heart M<Beating Heart> Chaining functions 
  • 135. Dead Heart M<Live Heart> M<Live Heart> M<Beating Heart> Chaining functions If we could change this type to M<Live Heart>, it would work! 
  • 136. M<Beating Heart>M<Live Heart> makeBeatingHeartM M<Beating Heart>Live Heart makeBeatingHeart Chaining functions This is what we’ve got: an M-generating function This is what we want: an M-thing only function
  • 137. M<Beating Heart>M<Live Heart> makeBeatingHeartM M<Beating Heart>Live Heart makeBeatingHeart Chaining functions bind "bind" converts an M-generating function into a M-thing only function
  • 138. "bind" for M-things bind World of M<_> things Normal World a M<b> World of M<_> things Normal World M<a> M<b> an M-generating function (diagonal)
  • 139. "bind" for M-things bind World of M<_> things Normal World a M<b> World of M<_> things Normal World M<a> M<b> a pure M-thing function (horizontal)
  • 140. Show me the code Beating Heart and "bind"
  • 141. let makeLiveHeart deadHeart = let becomeAlive vitalForce = // snipped (liveHeart, remainingVitalForce) M becomeAlive // signature // makeLiveHeart : DeadHeart -> M<LiveHeart> Demo: Chaining
  • 142. let makeBeatingHeart liveHeart = let becomeAlive vitalForce = // snipped (beatingHeart, remainingVitalForce) M becomeAlive // signature // makeBeatingHeart : LiveHeart -> M<BeatingHeart> Demo: Chaining
  • 143. let beatingHeartM = // Convert "diagonal" to "horizontal" let makeBeatingHeartM = bind makeBeatingHeart Demo: Chaining
  • 144. let beatingHeartM = // Convert "diagonal" to "horizontal" let makeBeatingHeartM = bind makeBeatingHeart // flow the data through each function DeadHeart "Anne" // DeadHeart |> makeLiveHeart // output = M<LiveHeart> |> makeBeatingHeartM // output = M<BeatingHeart> Demo: Chaining Q: Where did the vital force tracking go? A: We are silently threading data through the code. But no globals, no mutables!
  • 145. // run the M<BeatingHeart> with some vital force let beatingHeart, remainingFromHeart = runM beatingHeartM vf // val beatingHeart : BeatingHeart = // BeatingHeart ( // LiveHeart ("Anne",{units = 1}), // {units = 1} ) // // val remainingFromHeart : VitalForce = // {units = 8} // TWO units used up! Demo: Chaining Proof that we are silently threading the vital force through the code!
  • 147. "bind" for all elevated worlds bind Elevated World Normal World a E<b> Elevated World Normal World E<a> E<b> where "elevated world" is Option, List, Async, etc
  • 148. "bind" for all elevated worlds bind Elevated World Normal World a E<b> Elevated World Normal World E<a> E<b> where "elevated world" is Option, List, Async, etc
  • 149. The importance of bind World of normal values int string bool World of Lists List<int> List<string> List<bool> "Diagonal" functions
  • 150. The importance of bind World of normal values int string bool World of Lists List<int> List<string> List<bool> Bind "SelectMany“ in C#
  • 151. The importance of bind World of normal values int string bool World of Lists List<int> List<string> List<bool> Bind
  • 152. The importance of bind World of normal values int string bool World of Lists List<int> List<string> List<bool> Bind
  • 153. The importance of bind World of normal values int string bool World of Lists List<int> List<string> List<bool> “Horizontal" functions
  • 154. Technique 7: Lifting arbitrary functions Making "map3", "map4", "map5" on the fly
  • 155. type LiveBody = { leftLeg: LiveLeftLeg rightLeg : LiveLeftLeg leftArm : LiveLeftHealedArm rightArm : LiveRightArm head : LiveHead heart : BeatingHeart } Defining the whole body
  • 156. val createBody : leftLeg :LiveLeftLeg -> rightLeg :LiveLeftLeg -> leftArm :LiveLeftHealedArm -> rightArm :LiveRightArm -> head :LiveHead -> beatingHeart :BeatingHeart -> LiveBody // final result Creating the whole body Do we need a "mapSix" function?
  • 157. Introducing "apply" apply World of M<_> things M<(a->b)> World of M<_> things
  • 158. Introducing "apply" apply World of M<_> things M<(a->b)> World of M<_> things M<a> M<b>
  • 159. Introducing "apply" apply World of M<_> things M<(a->b)> World of M<_> things M<a> M<b> apply M<(a->b->c)> M<a> M<b->c>
  • 160. Introducing "apply" apply World of M<_> things M<(a->b)> World of M<_> things M<a> M<b> apply M<(a->b->c)> M<a> M<b->c> apply M<(a->b->c->d)> M<a> M<b->c->d>
  • 161. Using "apply" to make "map3" apply M<(a->b->c->d)> M<a> M<b->c->d>
  • 162. Using "apply" to make "map3" apply M<(b->c->d)> M<b> M<c->d> apply M<(a->b->c->d)> M<a> M<b->c->d>
  • 163. Using "apply" to make "map3" apply M<(b->c->d)> M<b> M<c->d> M<c->d> apply M<c> M<d> apply M<(a->b->c->d)> M<a> M<b->c->d>
  • 164. Using "apply" to make "map3" a->b->c->Result a b c Result
  • 165. Using "apply" to make "map3" M<(a->b->c->d)> a->b->c->Result a b c Result return
  • 166. Using "apply" to make "map3" apply M<(a->b->c->d)> M<a> a->b->c->Result a b c Result return create
  • 167. Using "apply" to make "map3" apply M<(a->b->c->d)> M<a> M<b> a->b->c->Result a b c Result return create create apply
  • 168. Using "apply" to make "map3" apply M<(a->b->c->d)> M<a> M<b> M<c> a->b->c->Result a b c Result return create create create apply apply
  • 169. Using "apply" to make "map3" apply M<(a->b->c->d)> M<a> M<b> M<c> M<Result> a->b->c->Result a b c Result return create create create apply apply
  • 170. Show me the code Whole body and "apply"
  • 171. // create the body in the "normal" world let createBody leftLeg rightLeg leftArm rightArm head heart = { leftLeg = leftLeg rightLeg = rightLeg leftArm = leftArm rightArm = rightArm head = head heart = heart } Demo: Whole body
  • 172. // <*> means "apply" let bodyM = returnM createBody <*> leftLegM <*> rightLegM <*> leftHealedArmM <*> rightArmM <*> headM <*> beatingHeartM // output is M<LiveBody> Demo: Whole body M-Things from earlier Output is still a potential thing. We're "programming"!
  • 173. // Lightning strikes! It's alive! let liveBody, remainingFromBody = runM bodyM vf // val liveBody : LiveBody = // {leftLeg = LiveLeftLeg ("Boris",{units = 1}) // rightLeg = LiveLeftLeg ("Boris",{units = 1}) // leftArm = LiveLeftArm ("Victor",{units = 1}) // rightArm = {lowerArm = LiveRightLowerArm // ("Tom",{units = 1}) // upperArm = LiveRightUpperArm // ("Jerry",{units = 1}) } // head = {brain = LiveBrain // ("Abby Normal",{units = 1}) // emptyHead = EmptyHead "Yorick"} // heart = BeatingHeart ( // LiveHeart ("Anne",{units = 1}), // {units = 1})} // val remainingFromBody : VitalForce = {units = 2} Demo: Whole body The state is automatically kept up-to-date
  • 174. Is your brain hurting now?
  • 175. Do we still have two problems?
  • 176. Live part B Vital force Become alive B! Remaining vital force Dead part B Live part A Vital force Become alive A! Remaining vital force Dead part A Connect the force between two steps using "bind" or "apply"
  • 177. Live part B Vital force Become alive B! Remaining vital force Dead part B Live part A Vital force Become alive A! Remaining vital force Dead part A Combine two outputs using "map2"
  • 180. The FunctionalToolbox • "map" – Lifts functions into the elevated world • "return" – Lifts values into the elevated world • "apply" – Lets you combine elevated values – "map2" is a just a specialized "apply“ • "bind" – Converts “diagonal” functions into horizontal ones
  • 181. The FunctionalToolbox • "map" – (with a sensible implementation) is a Functor • "return" and "apply" – (with a sensible implementation) is an Applicative • "return" and "bind" – (with a sensible implementation) is a Monad
  • 182. The State monad The state is threaded through the code "invisibly"
  • 183. let beatingHeartM = DeadHeart "Anne" |> makeLiveHeart |> makeBeatingHeartM // TWO units of force used up State monad Where is the "vital force" tracking variable?
  • 184. let bodyM = returnM createBody <*> leftLegM <*> rightLegM <*> leftHealedArmM <*> rightArmM <*> headM <*> beatingHeartM // EIGHT units of force used up State monad Where is the "vital force" variable? We are silently threading the vital force through the code... ...which allows us to focus on the design instead
  • 185. Using Dr Frankenfunctor's techniques in the real world Is this too academic? Too abstract to be useful?
  • 186. Scenario: Update user information • Input is {userId, name, email} • Step 1:Validate input – Could fail if name is blank, etc • Step 2: Canonicalize input – Trim blanks, lowercase email, etc • Step 3: Fetch existing record from db – Could fail if record is missing • Step 4: Update record in db
  • 188. Validate Canonicalize Generates a possible error Always succeeds
  • 189. Validate Canonicalize DbFetch Generates a possible error Generates a possible errorAlways succeeds
  • 190. Validate Canonicalize DbFetch DbUpdate Generates a possible error Generates a possible errorAlways succeeds Doesn't return How can we glue these mismatched functions together?
  • 191. World of normal things "lift" from this world World of two-track things to this world
  • 192. World of normal things World of two-track things bindmap apply
  • 196. Validate Canonicalize DbFetch DbUpdate Now we *can* glue these together easily! map bind tee, then map
  • 197. Summary • We've seen a toolkit of useful techniques – Don’t expect to understand them all straight away. • How to wrap a function into a type – A.k.a. a "computation" or "effect“ • How to use "map", "apply" and "bind" – Monads are not that scary – You can work with effects before running them! • How to thread state "invisibly" through code – Without using any globals or mutables!