Dr Frankenfunctor and the Monadster
-
Upload
scott-wlaschin -
Category
Technology
-
view
10.210 -
download
0
Transcript of Dr Frankenfunctor and the Monadster
![Page 1: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/1.jpg)
Dr Frankenfunctor and
the Monadster
@ScottWlaschin
fsharpforfunandprofit.com/monadster
![Page 2: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/2.jpg)
Warning
This talk contains:
– gruesome topics
– strained analogies
– discussion of monads
Not suitable for sensitive people (seriously)
![Page 3: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/3.jpg)
Functional programmers
love composition...
![Page 4: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/4.jpg)
A function Input Output
![Page 5: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/5.jpg)
function A function B Compose
![Page 6: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/6.jpg)
function A function B
![Page 7: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/7.jpg)
function A and B
Easy!
![Page 8: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/8.jpg)
... But here is a challenge for
function composition
![Page 9: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/9.jpg)
function A Input Output
function B Input Output 1
Output 2
function C Input 1 Output 1
Output 2 Input 2
function D Input 1 Output Input 2
![Page 10: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/10.jpg)
function A Input Output
function B Input Output 1
Output 2
function D Input 1 Output Input 2
How to compose?
![Page 11: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/11.jpg)
function A Input Output
function B Input Output 1
Output 2
function D Input 1 Output Input 2
How to compose?
![Page 12: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/12.jpg)
The answer: monads!
![Page 13: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/13.jpg)
The spread of the monad
• 1990 ACM Conference on LISP and Functional Programming
First monad in captivity
![Page 14: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/14.jpg)
The terrible events at the 1990 ACM Conference on LISP and Functional Programming
![Page 15: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/15.jpg)
The spread of the monad
• 1990 ACM Conference on LISP and Functional Programming
• 1991 Eugenio Moggi, "Notions of computation and monads"
• 1992 Philip Wadler, "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
![Page 16: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/16.jpg)
The spread of the monad
• 1990 ACM Conference on LISP and Functional Programming
• 1991 Eugenio Moggi, "Notions of computation and monads"
• 1992 Philip Wadler, "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
![Page 17: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/17.jpg)
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 Philip Wadler, "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
![Page 18: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/18.jpg)
The story of the Monadster
![Page 19: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/19.jpg)
The creature was built from body parts of various shapes
![Page 20: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/20.jpg)
The various parts were assembled into a whole
![Page 21: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/21.jpg)
The body was animated in a single instant, using a
bolt of lightning to create the vital force.
![Page 22: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/22.jpg)
... The Monadster
The “mark of the lambda”
![Page 23: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/23.jpg)
But how was it done?
I have devoted many years of
research into this matter...
![Page 24: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/24.jpg)
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.
![Page 25: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/25.jpg)
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
![Page 26: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/26.jpg)
Technique 1: Modelling with pure functions
![Page 27: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/27.jpg)
Become alive!
Vital force
Dead part Live part
Don't try this at home
![Page 28: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/28.jpg)
Live body part
Vital force
Become alive!
Remaining vital force
Dead body part
Two inputs
![Page 29: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/29.jpg)
Live body part
Vital force
Become alive!
Remaining vital force
Dead body part
Two outputs
![Page 30: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/30.jpg)
Live body part
Vital force
Become alive!
Remaining vital force
Dead body part
Less vital force available afterwards
![Page 31: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/31.jpg)
Live body part
Vital force
Become alive!
Remaining vital force
Dead body part
No globals, no mutation!
![Page 32: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/32.jpg)
But now you have two
problems...
![Page 33: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/33.jpg)
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?
![Page 34: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/34.jpg)
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?
![Page 35: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/35.jpg)
Technique 2: Wrapping the "Become Alive" function
Also, introducing schönfinkelling
![Page 36: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/36.jpg)
Moses Schönfinkel
invented schönfinkelling
![Page 37: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/37.jpg)
Moses Schönfinkel
invented schönfinkelling
![Page 38: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/38.jpg)
Haskell Curry
gave his name to currying
![Page 39: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/39.jpg)
Input A Uncurried Function
Input B Output C
Curried Function
Input A Intermediate
Function Output C Input B
What is currying?
after currying
Currying means that *every* function has one input
![Page 40: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/40.jpg)
// naming a lambda Func<int,int> add1 = (y => 1 + y) // using it var three = add1(2)
Currying examples
![Page 41: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/41.jpg)
// naming a lambda let add1 = (fun y -> 1 + y) // using it let three = add1 2
Currying examples
![Page 42: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/42.jpg)
// 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
![Page 43: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/43.jpg)
// "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
![Page 44: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/44.jpg)
// removing the parens let three = add 1 2
Currying examples
// returning a lambda with baked in "x" let add x = (fun y -> x + y)
![Page 45: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/45.jpg)
Live part A
Vital force
Become alive!
Remaining vital force
Dead part A
Currying "become alive!"
![Page 46: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/46.jpg)
Become alive!
Dead part A Vital force
Live part A
Currying "become alive!"
![Page 47: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/47.jpg)
Become alive!
Dead part A Vital force
M<Live Part A>
Live part A
Wrapping the function
"M" is for "Monadster"
![Page 48: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/48.jpg)
Become alive!
Dead part A Vital force
M<Live Part A>
Live part A
Wrapping the function
![Page 49: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/49.jpg)
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
![Page 50: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/50.jpg)
M<Live Part A> Run
Live part A
Remaining vital force
Running the function
Vital force
![Page 51: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/51.jpg)
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>
![Page 52: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/52.jpg)
Show me the code
Left Leg
![Page 53: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/53.jpg)
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
![Page 54: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/54.jpg)
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
![Page 55: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/55.jpg)
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
![Page 56: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/56.jpg)
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
![Page 57: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/57.jpg)
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
![Page 58: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/58.jpg)
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
![Page 59: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/59.jpg)
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>
![Page 60: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/60.jpg)
// 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
![Page 61: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/61.jpg)
Technique 3:
Transforming live parts
![Page 62: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/62.jpg)
A Broken Arm
Dead Broken Arm
What we've got
Live Healed Arm
What we want
![Page 63: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/63.jpg)
Healing a broken arm
Live Healed Arm Live Broken Arm HealBrokenArm
We have this function!
![Page 64: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/64.jpg)
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...
![Page 65: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/65.jpg)
Create
Dead Broken Arm Dead Healed Arm
Live Healed Arm
Healing a broken arm
HealBrokenArm
![Page 66: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/66.jpg)
Create
Dead Broken Arm Dead Healed Arm
Live Healed Arm
No. We can only heal live arms
Healing a broken arm
HealBrokenArm
![Page 67: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/67.jpg)
Dead Broken Arm
Live Healed Arm Live Broken Arm
Create
HealBrokenArm
Healing a broken arm
![Page 68: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/68.jpg)
Dead Broken Arm
Live Healed Arm Live Broken Arm
Create
HealBrokenArm
No. We can't create live things directly, only M-type things
Healing a broken arm
![Page 69: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/69.jpg)
Dead Broken Arm
M<Live Healed Arm> M<Live Broken Arm>
Create
HealBrokenArm
Healing a broken arm
![Page 70: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/70.jpg)
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
![Page 71: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/71.jpg)
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
![Page 72: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/72.jpg)
Live Healed Arm Live 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
![Page 73: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/73.jpg)
Live Healed Arm Live Broken Arm HealBrokenArm
Healing a broken arm
M<Live Healed Arm> M<Live Broken Arm> HealBrokenArmM
map
![Page 74: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/74.jpg)
"map" is generic for M-things
Normal World
a b
![Page 75: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/75.jpg)
"map" is generic for M-things
Normal World
a b
map
![Page 76: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/76.jpg)
"map" is generic for M-things
Normal World
a b
map
World of M<_> things
M<a> M<b>
A function in the world of M-things
“lifting”
![Page 77: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/77.jpg)
Show me the code
Broken Arm and "map"
![Page 78: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/78.jpg)
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
![Page 79: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/79.jpg)
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
![Page 80: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/80.jpg)
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
![Page 81: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/81.jpg)
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
![Page 82: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/82.jpg)
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
![Page 83: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/83.jpg)
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.
![Page 84: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/84.jpg)
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
![Page 85: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/85.jpg)
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
![Page 86: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/86.jpg)
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}
![Page 87: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/87.jpg)
The importance of map
![Page 88: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/88.jpg)
The "map" pattern for elevated worlds
map
Elevated World
Normal World
a b
Elevated World
Normal World
E<a> E<b>
A function in the world of normal things
where "elevated world" is Option, List, Async, etc
![Page 89: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/89.jpg)
The "map" pattern for elevated worlds
map
Elevated World
Normal World
a b
Elevated World
Normal World
E<a> E<b>
A function in the world of E-things
where "elevated world" is Option, List, Async, etc
![Page 90: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/90.jpg)
The importance of map
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
![Page 91: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/91.jpg)
The importance of map
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
![Page 92: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/92.jpg)
The importance of map
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
![Page 93: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/93.jpg)
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
![Page 94: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/94.jpg)
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
![Page 95: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/95.jpg)
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
![Page 96: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/96.jpg)
How not to code with lists
addTwo
World of normal values
World of Lists
![Page 97: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/97.jpg)
How to code with lists
addTwo_L
World of normal values
World of Lists
![Page 98: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/98.jpg)
How to code with lists
T -> U
List<T> -> List<U>
List.map
World of normal values
World of Lists
Linq.Select
![Page 99: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/99.jpg)
How to code with lists
addTwo
addTwo_L [1;2] |>
1 |> // 3
// [3;4]
World of normal values
World of Lists
![Page 100: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/100.jpg)
// 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
![Page 101: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/101.jpg)
Technique 4:
Combining two live parts
![Page 102: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/102.jpg)
Combining two parts
Dead Lower Arm
Dead Upper Arm
Live Whole Arm
What we've got What we want
![Page 103: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/103.jpg)
Combining two parts
Live Arm Live Lower Arm ArmSurgery
Live Whole Arm
Live Upper Arm
We have this function!
![Page 104: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/104.jpg)
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
![Page 105: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/105.jpg)
Live Arm
Combining two parts
Dead Lower Arm Dead Upper Arm Dead Arm
Create
ArmSurgery
![Page 106: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/106.jpg)
Live Arm
Combining two parts
Dead Lower Arm Dead Upper Arm Dead Arm
Create
No. Only works on live arms
ArmSurgery
![Page 107: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/107.jpg)
Create
ArmSurgery
Combining two parts
Dead Lower Arm Dead Upper Arm
Live Lower Arm Live Upper Arm Live Arm
Create
![Page 108: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/108.jpg)
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
![Page 109: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/109.jpg)
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
![Page 110: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/110.jpg)
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
![Page 111: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/111.jpg)
Combining two parts
map2
ArmSurgery Live Lower Arm Live Upper Arm Live Arm
ArmSurgeryM M<LiveLowerArm> M<LiveUpperArm> M<LiveArm>
![Page 112: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/112.jpg)
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
![Page 113: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/113.jpg)
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
![Page 114: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/114.jpg)
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
![Page 115: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/115.jpg)
Technique 5:
Combining live and dead parts
![Page 116: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/116.jpg)
Combining mismatched parts
Empty Head Dead Brain
What we've got
Live Head
What we want
![Page 117: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/117.jpg)
Combining mismatched parts
Live Head Live Brain HeadSurgery Empty Head
Combining function alive not alive
![Page 118: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/118.jpg)
Create
HeadSurgery
Combining mismatched parts
Dead Brain Empty Head
Live Brain Empty Head Live Head
Copy
![Page 119: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/119.jpg)
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
![Page 120: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/120.jpg)
Create
HeadSurgeryM
Combining mismatched parts
Dead Brain Empty Head
M<Live Brain> M<Empty Head> M<Live Head>
![Page 121: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/121.jpg)
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
![Page 122: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/122.jpg)
Combining mismatched parts
return
Anything
M<Anything>
![Page 123: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/123.jpg)
Create
HeadSurgeryM
Combining mismatched parts
Dead Brain
M<Live Brain> M<Empty Head> M<Live Head>
return
Empty Head
![Page 124: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/124.jpg)
Create
HeadSurgeryM
Combining mismatched parts
Dead Brain
M<Live Brain> M<Empty Head> M<Live Head>
return
Empty Head
Both are M-things now
![Page 125: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/125.jpg)
Create
HeadSurgeryM
Combining mismatched parts
Dead Brain
M<Live Brain> M<Empty Head> M<Live Head>
map2
Empty Head
Live Head Live Brain HeadSurgery Empty Head
return
![Page 126: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/126.jpg)
"return" for M-things
return
Normal World
a
World of M<_> things
A value in the world of normal things
![Page 127: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/127.jpg)
"return" for M-things
return
Normal World
a
World of M<_> things
M<a>
A value in the world of M-things
![Page 128: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/128.jpg)
"return" for all elevated worlds
return
Normal World
a
Elevated World
E<a>
A value in the world of normal things
A value in the world of E-things
![Page 129: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/129.jpg)
Technique 6:
Chaining M-generating functions
![Page 130: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/130.jpg)
Chaining functions
Beating Heart Dead Heart
What we want What we've got
![Page 131: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/131.jpg)
Chaining functions
Beating Heart Live Heart Dead Heart
Creating a beating heart is a two-step process
![Page 132: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/132.jpg)
Chaining functions
Dead Heart M<Live Heart> Live Heart M<Beating Heart>
We have an M-generating function
We have another M-generating function
![Page 133: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/133.jpg)
Dead Heart M<Live Heart>
Live Heart M<Beating Heart>
Chaining functions
Output type doesn't match input type
![Page 134: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/134.jpg)
Dead Heart M<Live Heart>
Live Heart M<Beating Heart>
Chaining functions
![Page 135: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/135.jpg)
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!
![Page 136: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/136.jpg)
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
![Page 137: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/137.jpg)
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
![Page 138: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/138.jpg)
"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)
![Page 139: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/139.jpg)
"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)
![Page 140: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/140.jpg)
Show me the code
Beating Heart and "bind"
![Page 141: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/141.jpg)
let makeLiveHeart deadHeart = let becomeAlive vitalForce = // snipped (liveHeart, remainingVitalForce) M becomeAlive // signature // makeLiveHeart : DeadHeart -> M<LiveHeart>
Demo: Chaining
![Page 142: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/142.jpg)
let makeBeatingHeart liveHeart = let becomeAlive vitalForce = // snipped (beatingHeart, remainingVitalForce) M becomeAlive // signature // makeBeatingHeart : LiveHeart -> M<BeatingHeart>
Demo: Chaining
![Page 143: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/143.jpg)
let beatingHeartM = // Convert "diagonal" to "horizontal" let makeBeatingHeartM = bind makeBeatingHeart
Demo: Chaining
![Page 144: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/144.jpg)
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!
![Page 145: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/145.jpg)
// 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!
![Page 146: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/146.jpg)
The importance of bind
![Page 147: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/147.jpg)
"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
![Page 148: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/148.jpg)
"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
![Page 149: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/149.jpg)
The importance of bind
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
"Diagonal" functions
![Page 150: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/150.jpg)
The importance of bind
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
Bind
"SelectMany“ in C#
![Page 151: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/151.jpg)
The importance of bind
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
Bind
![Page 152: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/152.jpg)
The importance of bind
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
Bind
![Page 153: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/153.jpg)
The importance of bind
World of normal values
int string bool
World of Lists
List<int> List<string> List<bool>
“Horizontal" functions
![Page 154: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/154.jpg)
Technique 7:
Lifting arbitrary functions
Making "map3", "map4", "map5"
on the fly
![Page 155: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/155.jpg)
type LiveBody = { leftLeg: LiveLeftLeg rightLeg : LiveLeftLeg leftArm : LiveLeftHealedArm rightArm : LiveRightArm head : LiveHead heart : BeatingHeart }
Defining the whole body
![Page 156: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/156.jpg)
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?
![Page 157: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/157.jpg)
Introducing "apply"
apply World of M<_> things
M<(a->b)>
World of M<_> things
![Page 158: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/158.jpg)
Introducing "apply"
apply World of M<_> things
M<(a->b)>
World of M<_> things
M<a> M<b>
![Page 159: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/159.jpg)
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>
![Page 160: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/160.jpg)
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>
![Page 161: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/161.jpg)
Using "apply" to make "map3"
apply M<(a->b->c->d)> M<a> M<b->c->d>
![Page 162: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/162.jpg)
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>
![Page 163: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/163.jpg)
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>
![Page 164: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/164.jpg)
Using "apply" to make "map3"
a->b->c->Result a b c Result
![Page 165: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/165.jpg)
Using "apply" to make "map3"
M<(a->b->c->d)>
a->b->c->Result a b c Result
return
![Page 166: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/166.jpg)
Using "apply" to make "map3"
apply M<(a->b->c->d)> M<a>
a->b->c->Result a b c Result
return create
![Page 167: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/167.jpg)
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
![Page 168: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/168.jpg)
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
![Page 169: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/169.jpg)
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
![Page 170: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/170.jpg)
Show me the code
Whole body and "apply"
![Page 171: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/171.jpg)
// 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
![Page 172: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/172.jpg)
// <*> 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"!
![Page 173: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/173.jpg)
// 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
![Page 174: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/174.jpg)
Is your brain hurting now?
![Page 175: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/175.jpg)
Do we still have two problems?
![Page 176: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/176.jpg)
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"
![Page 177: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/177.jpg)
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"
![Page 178: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/178.jpg)
A Functional Toolbox
![Page 179: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/179.jpg)
map
return bind
map2
apply
![Page 180: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/180.jpg)
The Functional Toolbox
• "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
![Page 181: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/181.jpg)
The Functional Toolbox
• "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
![Page 182: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/182.jpg)
The State monad
The state is threaded through the
code "invisibly"
![Page 183: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/183.jpg)
let beatingHeartM = DeadHeart "Anne" |> makeLiveHeart |> makeBeatingHeartM // TWO units of force used up
State monad
Where is the "vital force" tracking variable?
![Page 184: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/184.jpg)
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
![Page 185: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/185.jpg)
Using Dr Frankenfunctor's
techniques in the real world
Is this too academic? Too abstract to be useful?
![Page 186: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/186.jpg)
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
![Page 187: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/187.jpg)
Validate
Generates a possible error
![Page 188: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/188.jpg)
Validate Canonicalize
Generates a possible error Always succeeds
![Page 189: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/189.jpg)
Validate Canonicalize DbFetch
Generates a possible error Generates a possible error Always succeeds
![Page 190: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/190.jpg)
Validate Canonicalize DbFetch DbUpdate
Generates a possible error Generates a possible error Always succeeds Doesn't return
How can we glue these mismatched functions together?
![Page 191: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/191.jpg)
World of normal things
"lift" from this world
World of two-track things
to this world
![Page 192: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/192.jpg)
World of normal things
World of two-track things
bind map apply
![Page 193: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/193.jpg)
map
Converting everything to two-track
![Page 194: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/194.jpg)
bind
map
Converting everything to two-track
![Page 195: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/195.jpg)
bind
map
tee map
Converting everything to two-track
![Page 196: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/196.jpg)
Validate Canonicalize DbFetch DbUpdate
Now we *can* glue these together easily!
map bind tee, then map
![Page 197: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/197.jpg)
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!
![Page 198: Dr Frankenfunctor and the Monadster](https://reader031.fdocuments.net/reader031/viewer/2022030209/58adff1d1a28abf0628b636b/html5/thumbnails/198.jpg)
Thanks!
@ScottWlaschin
fsharpforfunandprofit.com/monadster
Contact me
Slides and video here
Let us know if you need help with F#