SlideShare ist ein Scribd-Unternehmen logo
1 von 191
Downloaden Sie, um offline zu lesen
The Power Of Composition
NDC Oslo 2020
@ScottWlaschin
fsharpforfunandprofit.com
The Power Of Composition
1. The philosophy of composition
2. Ideas of functional programming
– Functions and how to compose them
– Types and how to compose them
3. Composition in practice
– Roman Numerals
– FizzBuzz gone functional
– Uh oh, monads!
– A web service
THE PHILOSOPHY OF
COMPOSITION
Prerequisites for
understanding composition
• You must have been a child at some point
• You must have played with Lego
• You must have played with toy trains
Lego
Philosophy
Lego Philosophy
1. All pieces are designed to be connected
2. The pieces are reusable in many contexts
3. Connect two pieces together and get
another "piece" that can still be connected
All pieces are designed to be connected
The pieces are reusable in different contexts
Connect two pieces together and
get another "piece" that can still be connected
Make big things from small things in the same way
Wooden Railway Track Philosophy
1. All pieces are designed to be connected
2. The pieces are reusable in many contexts
3. Connect two pieces together and get
another "piece" that can still be connected
All pieces are designed to be connected
The pieces are reusable in different contexts
Connect two pieces together and get
another "piece" that can still be connected
You can keep adding and adding.
Make big things from small things in the same way
If you understand Lego and wooden
railways, then you know
everything about composition!
THE IDEAS OF
FUNCTIONAL PROGRAMMING
Four ideas behind FP
Function
3.Types are not classes
1. Functions are things
2. Build bigger functions using
composition
4. Build bigger types using
composition
FP idea #1:
Functions are things
Function
The Tunnel of
Transformation
Function
apple -> banana
A function is a thing which
transforms inputs to outputs
A function is a standalone thing,
not attached to a class
A function is a standalone thing,
not attached to a class
It can be used for inputs and outputs
of other functions
A function can be an output thing
input
output
A function can be an input thing
input output
A function can be a parameter
input
output
input output
FP idea #2:
Build bigger functions
using composition
Function 1
apple -> banana
Function 2
banana -> cherry
>>
Function 1
apple -> banana
Function 2
banana -> cherry
New Function
apple -> cherry
Can't tell it was built
from smaller functions!
Where did the banana go?
Function composition in F# and C#
using the "piping" approach
int add1(int x) => x + 1;
int times2(int x) => x * 2;
int square(int x) => x * x;
add1(5); // = 6
times2(add1(5)); // = 12
square(times2(add1(5))); // = 144
Nested function calls
can be confusing if too deep
add15 6 times2 12 square 144
5 |> add1 // = 6
5 |> add1 |> times2 // = 12
5 |> add1 |> times2 |> square // = 144
add1 times2 square5 6 12 144
F# example
add1 times2 square5 6 12 144
5.Pipe(add1);
5.Pipe(add1).Pipe(times2);
5.Pipe(add1).Pipe(times2).Pipe(square);
C# example
Building big things from functions
It's compositions all the way up
Low-level operation
ToUpper
stringstring
Low-level operation
Service
AddressValidator
A “Service” is just like a microservice
but without the "micro" in front
Validation
Result
Address
Low-level operation Low-level operation
Service
Use-case
UpdateProfileData
ChangeProfile
Result
ChangeProfile
Request
Service Service
Use-case
Web application
Http
Response
Http
Request
Use-case Use-case
Http
Response
Http
Request
Even for complex applications,
data flows only in one direction
FP idea #3:
Types are not classes
So, what is a type then?
A type is a just a name
for a set of things
Set of
valid inputs
Set of
valid outputs
Function
Set of
valid inputs
Set of
valid outputs
Function
1
2
3
4
5
6
This is type
"integer"
A type is a just a name
for a set of things
Set of
valid inputs
Set of
valid outputs
Function
This is type
"string"
"abc"
"but"
"cobol"
"double"
"end"
"float"
A type is a just a name
for a set of things
Set of
valid inputs
Set of
valid outputs
Function
This is type
"Person"
Donna Roy
Javier Mendoza
Nathan Logan
Shawna Ingram
Abel Ortiz
Lena Robbins
GordonWood
A type is a just a name
for a set of things
Set of
valid inputs
Set of
valid outputs
Function
This is type
"Fruit"
A type is a just a name
for a set of things
Set of
valid inputs
Set of
valid outputs
Function
This is a type of
Fruit->Fruit functions
A type is a just a name
for a set of things
FP idea #4:
Types can be composed too
Algebraic type system
Bigger types are built from smaller types by:
Composing with “AND”
Composing with “OR”
FruitSalad =
AND AND
Compose with “AND”
Compose with “AND”
enum AppleVariety { Red, Green }
enum BananaVariety { Yellow, Brown }
enum CherryVariety { Tart, Sweet }
struct FruitSalad
{
AppleVariety Apple;
BananaVariety Banana;
CherryVariety Cherry;
}
C# example
Apple AND
Banana AND
Cherry
Compose with “AND”
type AppleVariety = Red | Green
type BananaVariety = Yellow | Brown
type CherryVariety = Tart | Sweet
type FruitSalad = {
Apple: AppleVariety
Banana: BananaVariety
Cherry: CherryVariety
}
F# example
Snack = OR OR
Compose with “OR”
type Snack =
| Apple of AppleVariety
| Banana of BananaVariety
| Cherry of CherryVariety
A real world example
of composing types
Some requirements:
We accept three forms of payment:
Cash, Paypal, or CreditCard.
For Cash we don't need any extra information
For Paypal we need an email address
For Cards we need a card type and card number
interface IPaymentMethod
{..}
class Cash() : IPaymentMethod
{..}
class Paypal(string emailAddress): IPaymentMethod
{..}
class Card(string cardType, string cardNo) : IPaymentMethod
{..}
In OO design you would probably implement it as an
interface and a set of subclasses, like this:
type EmailAddress = string
type CardNumber = string
In F# you would probably implement by composing
types, like this:
type EmailAddress = ...
type CardNumber = …
type CardType = Visa | Mastercard
type CreditCardInfo = {
CardType : CardType
CardNumber : CardNumber
}
type EmailAddress = ...
type CardNumber = ...
type CardType = ...
type CreditCardInfo = ...
type PaymentMethod =
| Cash
| PayPal of EmailAddress
| Card of CreditCardInfo
type EmailAddress = ...
type CardNumber = ...
type CardType = ...
type CreditCardInfo = ...
type PaymentMethod =
| Cash
| PayPal of EmailAddress
| Card of CreditCardInfo
type PaymentAmount = decimal
type Currency = EUR | USD | RUB
type EmailAddress = ...
type CardNumber = ...
type CardType = ...
type CreditCardInfo = ...
type PaymentMethod =
| Cash
| PayPal of EmailAddress
| Card of CreditCardInfo
type PaymentAmount = decimal
type Currency = EUR | USD | RUB
type Payment = {
Amount : PaymentAmount
Currency : Currency
Method : PaymentMethod }
type EmailAddress = ...
type CardNumber = ...
type CardType = ...
type CreditCardInfo = ...
type PaymentMethod =
| Cash
| PayPal of EmailAddress
| Card of CreditCardInfo
type PaymentAmount = decimal
type Currency = EUR | USD | RUB
type Payment = {
Amount : PaymentAmount
Currency : Currency
Method : PaymentMethod }
Composable types can be used as
executable documentation
type Deal = Deck -> (Deck * Card)
type PickupCard = (Hand * Card) -> Hand
type Suit = Club | Diamond | Spade | Heart
type Rank = Two | Three | Four | Five | Six | Seven | Eight
| Nine | Ten | Jack | Queen | King | Ace
type Card = { Suit:Suit; Rank:Rank }
type Hand = Card list
type Deck = Card list
type Player = {Name:string; Hand:Hand}
type Game = { Deck:Deck; Players:Player list }
The domain on one screen!
type CardType = Visa | Mastercard
type CardNumber = string
type EmailAddress = string
type PaymentMethod =
| Cash
| PayPal of EmailAddress
| Card of CreditCardInfo
| Bitcoin of BitcoinAddress
A big topic and not enough time  
More on DDD and designing with types at
fsharpforfunandprofit.com/ddd
Composition in practice:
Time for some real examples!
COMPOSITIONWITH PIPING
(ROMAN NUMERALS)
Technique #1
To Roman Numerals
• Task: How to convert an arabic integer
to roman numerals?
• 5 => "V"
• 12 => "XII"
• 107 => "CVII"
To Roman Numerals
To Roman Numerals
• Use the "tally" approach
– Start with N copies of "I"
– Replace five "I"s with a "V"
– Replace two "V"s with a "X"
– Replace five "X"s with a "L"
– Replace two "L"s with a "C"
– etc
To Roman Numerals
number
etc
Replicate "I"
Replace_IIIII_V
Replace_VV_X
Replace_XXXXX_L
string ToRomanNumerals(int number)
{
// define a helper function for each step
string replace_IIIII_V(string s) =>
s.Replace("IIIII", "V");
string replace_VV_X(string s) =>
s.Replace("VV", "X");
string replace_XXXXX_L(string s) =>
s.Replace("XXXXX", "L");
string replace_LL_C(string s) =>
s.Replace("LL", "C");
// then combine them using piping
return new string('I', number)
.Pipe(replace_IIIII_V)
.Pipe(replace_VV_X)
.Pipe(replace_XXXXX_L)
.Pipe(replace_LL_C);
}
C# example
let toRomanNumerals number =
// define a helper function for each step
let replace_IIIII_V str =
replace "IIIII" "V" str
let replace_VV_X str =
replace "VV" "X" str
let replace_XXXXX_L str =
replace "XXXXX" "L" str
let replace_LL_C str =
replace "LL" "C" str
// then combine them using piping
String.replicate number "I"
|> replace_IIIII_V
|> replace_VV_X
|> replace_XXXXX_L
|> replace_LL_C
F# example
IT'S NOT ALWAYSTHIS
EASY…
function A function BCompose
function A function B
function A and B
Easy!
... But here is a challenge
function AInput Output
function B
Input 1 Output
Input 2
function AInput Output
function B
Input 1 Output
Input 2
Challenge #1: How can
we compose these?

COMPOSITION WITH CURRYING
(ROMAN NUMERALS)
Technique #2
The Replace function
oldValue outputString
newValue
inputString
Replace
Uh-oh! Composition problem
Replace I / V Replace V / X Replace X / L 
Bad news:
Composition patterns
only work for functions that
have one parameter! 
Good news!
Every function can be turned into
a one parameter function 
Haskell Curry
We named this technique after him
Input A
Uncurried
Function
Input B
Output C
Curried
Function
Input A
Intermediate
Function
Output CInput B
What is currying?
after currying
Function as output
Input A
Uncurried
Function
Input B
Output C
Curried
Function
Input A
Intermediate
Function
Output CInput B
What is currying?
One input One input
Currying means that *every* function can be converted
to a series of one input functions
Replace
Before currying
input.Replace(oldValue, newValue);
string output
Replace
Old New
Old
New
After currying
Func<string,string> replace(string oldVal, string newVal) =>
input => input.Replace(oldVal, newVal);
Replace
Old New
Old
New
After currying
Func<string,string> replace(string oldVal, string newVal) =>
input => input.Replace(oldVal, newVal);
Func<string,string> replace(string oldVal, string newVal) =>
input => input.Replace(oldVal, newVal);
Replace
Old New
Old
New
After currying
This lambda (function) is returned
one-parameter
function
string ToRomanNumerals(int number)
{
// define a general helper function
Func<string,string> replace(
string oldValue, string newValue) =>
input => input.Replace(oldValue, newValue);
// then use piping
return new string('I', number)
.Pipe(replace("IIIII","V"))
.Pipe(replace("VV","X"))
.Pipe(replace("XXXXX","L"))
.Pipe(replace("LL","C"));
}
C# example
string ToRomanNumerals(int number)
{
// define a general helper function
Func<string,string> replace(
string oldValue, string newValue) =>
input => input.Replace(oldValue, newValue);
// then use piping
return new string('I', number)
.Pipe(replace("IIIII","V"))
.Pipe(replace("VV","X"))
.Pipe(replace("XXXXX","L"))
.Pipe(replace("LL","C"));
}
C# example
string ToRomanNumerals(int number)
{
// define a general helper function
Func<string,string> replace(
string oldValue, string newValue) =>
input => input.Replace(oldValue, newValue);
// then use piping
return new string('I', number)
.Pipe(replace("IIIII","V"))
.Pipe(replace("VV","X"))
.Pipe(replace("XXXXX","L"))
.Pipe(replace("LL","C"));
}
C# example
Only 2 of the 3
parameters are passed in
The other
parameter comes
from the pipeline
let toRomanNumerals number =
// no helper function needed.
// currying occurs automatically in F#
// combine using piping
String.replicate number "I"
|> replace "IIIII" "V"
|> replace "VV" "X"
|> replace "XXXXX" "L"
|> replace "LL" "C"
F# example
let toRomanNumerals number =
// no helper function needed.
// currying occurs automatically in F#
// combine using piping
String.replicate number "I"
|> replace "IIIII" "V"
|> replace "VV" "X"
|> replace "XXXXX" "L"
|> replace "LL" "C"
Only 2 of the 3
parameters are passed in
F# example
The other
parameter comes
from the pipeline
Partial Application
Partial Application
let add x y = x + y
let multiply x y = x * y
5
|> add 2
|> multiply 3
Piping provides the missing argument
partial application
Partial Application
Replace ReplaceOldNew
Old New
Old
New
String.replicate number "I"
|> replace "IIIII" "V"
|> replace "VV" "X"
|> replace "XXXXX" "L"
|> replace "LL" "C"
Only 2 parameters
passed in
Piping provides the missing argument
Pipelines
are extensible
let toRomanNumerals number =
String.replicate number "I"
|> replace "IIIII" "V"
|> replace "VV" "X"
|> replace "XXXXX" "L"
|> replace "LL" "C"
Composable => extensible
// can easily add new segments to the pipeline
|> replace "VIIII" "IX"
|> replace "IIII" "IV"
|> replace "LXXXX" "XC"
functionInput Output
function
Input 1 Output
Input 2
Challenge #1: How can we compose these?

Here is another challenge
function AInput Output
function BInput
Output 1
Output 2
function AInput Output
function BInput
Output 1
Output 2
Challenge #2: How can we compose these?

COMPOSITIONWITH BIND
(FIZZBUZZ)
Technique #3
FizzBuzz definition
Write a program that takes a number as input
• For multiples of three print "Fizz"
• For multiples of five print "Buzz"
• For multiples of both three and five print "FizzBuzz"
• Otherwise, print the original number
let fizzBuzz n =
if (isDivisibleBy n 15) then
printfn "FizzBuzz"
else if (isDivisibleBy n 3) then
printfn "Fizz"
else if (isDivisibleBy n 5) then
printfn "Buzz"
else
printfn "%i" n
let isDivisibleBy n divisor =
(n % divisor) = 0 // helper function
A simple F# implementation
let fizzBuzz n =
if (isDivisibleBy n 15) then
printfn "FizzBuzz"
else if (isDivisibleBy n 3) then
printfn "Fizz"
else if (isDivisibleBy n 5) then
printfn "Buzz"
else
printfn "%i" n
let isDivisibleBy n divisor =
(n % divisor) = 0 // helper function
A simple F# implementation
Pipeline implementation
number Handle 15 case
Pipeline implementation
Handle 3 case
number Handle 15 case
Pipeline implementation
Handle 3 case
Handle 5 case
number Handle 15 case
Pipeline implementation
Handle 3 case
Handle 5 case
number
Answer
Handle 15 case
Last step
number Handle case
Handled
(e.g. "Fizz", "Buzz")
Unhandled
(e.g. 2, 7, 13)
Unhandled
Handled
Input ->
or
Unhandled
Handled
Input ->
type FizzBuzzResult =
| Unhandled of int // the original int
| Handled of string // "Fizz", Buzz", etc
Idea from http://weblog.raganwald.com/2007/01/dont-overthink-fizzbuzz.html
or
type FizzBuzzResult =
| Unhandled of int // the original int
| Handled of string // "Fizz", Buzz", etc
let handle divisor label n =
if (isDivisibleBy n divisor) then
Handled label
else
Unhandled n
Idea from http://weblog.raganwald.com/2007/01/dont-overthink-fizzbuzz.html
type FizzBuzzResult =
| Unhandled of int // the original int
| Handled of string // "Fizz", Buzz", etc
let handle divisor label n =
if (isDivisibleBy n divisor) then
Handled label
else
Unhandled n
12 |> handle 3 "Fizz" // Handled "Fizz"
10 |> handle 3 "Fizz" // Unhandled 10
10 |> handle 5 "Buzz" // Handled "Buzz"
handle 5 "Buzz"
let fizzbuzz n =
let result15 = n |> handle 15 "FizzBuzz"
match result15 with
| Handled str ->
str
| Unhandled n ->
let result3 = n |> handle 3 "Fizz"
match result3 with
| Handled str ->
str
| Unhandled n ->
let result5 = n |> handle 5 "Buzz"
match result5 with
| Handled str ->
str
| Unhandled n ->
string n // convert to string
First implementation attempt
let fizzbuzz n =
let result15 = n |> handle 15 "FizzBuzz"
match result15 with
| Handled str ->
str
| Unhandled n ->
let result3 = n |> handle 3 "Fizz"
match result3 with
| Handled str ->
str
| Unhandled n ->
let result5 = n |> handle 5 "Buzz"
match result5 with
| Handled str ->
str
| Unhandled n ->
// do something with Unhandled value
let fizzbuzz n =
let result15 = n |> handle 15 "FizzBuzz"
match result15 with
| Handled str ->
str
| Unhandled n ->
let result3 = n |> handle 3 "Fizz"
match result3 with
| Handled str ->
str
| Unhandled n ->
// do something with Unhandled value
// ...
// ...
let fizzbuzz n =
let result15 = n |> handle 15 "FizzBuzz"
match result15 with
| Handled str ->
str
| Unhandled n ->
// do something with Unhandled value
// ...
// ...
if Handled then
// return the string
if Unhandled then
// do something with the number
If Unhandled
If Handled
Bypass and
return the string
let ifUnhandledDo f result =
match result with
| Handled str ->
Handled str
| Unhandled n ->
f n
let fizzbuzz n =
n
|> handle 15 "FizzBuzz"
|> ifUnhandledDo (handle 3 "Fizz")
|> ifUnhandledDo (handle 5 "Buzz")
|> lastStep
let fizzbuzz n =
n
|> handle 15 "FizzBuzz"
|> ifUnhandledDo (handle 3 "Fizz")
|> ifUnhandledDo (handle 5 "Buzz")
|> lastStep
let fizzbuzz n =
n
|> handle 15 "FizzBuzz"
|> ifUnhandledDo (handle 3 "Fizz")
|> ifUnhandledDo (handle 5 "Buzz")
|> lastStep
let fizzbuzz n =
n
|> handle 15 "FizzBuzz"
|> ifUnhandledDo (handle 3 "Fizz")
|> ifUnhandledDo (handle 5 "Buzz")
|> lastStep
let fizzbuzz n =
n
|> handle 15 "FizzBuzz"
|> ifUnhandledDo (handle 3 "Fizz")
|> ifUnhandledDo (handle 5 "Buzz")
|> lastStep
let lastStep result =
match result with
| Handled str ->
str
| Unhandled n ->
string(n) // convert to string
let fizzbuzz n =
n
|> handle 15 "FizzBuzz"
|> ifUnhandledDo (handle 3 "Fizz")
|> ifUnhandledDo (handle 5 "Buzz")
|> lastStep
Composable => easy to extend
let fizzbuzz n =
n
|> handle 15 "FizzBuzz"
|> ifUnhandledDo (handle 3 "Fizz")
|> ifUnhandledDo (handle 5 "Buzz")
|> ifUnhandledDo (handle 7 "Baz")
|> lastStep
Composable => easy to extend
let fizzbuzz n =
n
|> handle 15 "FizzBuzz"
|> ifUnhandledDo (handle 3 "Fizz")
|> ifUnhandledDo (handle 5 "Buzz")
|> ifUnhandledDo (handle 7 "Baz")
|> ifUnhandledDo (handle 11 "Pozz")
|> lastStep
Composable => easy to extend
let fizzbuzz n =
n
|> handle 15 "FizzBuzz"
|> ifUnhandledDo (handle 3 "Fizz")
|> ifUnhandledDo (handle 5 "Buzz")
|> ifUnhandledDo (handle 7 "Baz")
|> ifUnhandledDo (handle 11 "Pozz")
|> ifUnhandledDo (handle 13 "Tazz")
|> lastStep
Composable => easy to extend
Another example:
Chaining tasks
When task
completesWait Wait
a.k.a "promise", "future"
let taskExample input =
let taskX = startTask input
taskX.WhenFinished (fun x ->
let taskY = startAnotherTask x
taskY.WhenFinished (fun y ->
let taskZ = startThirdTask y
taskZ.WhenFinished (fun z ->
etc
let taskExample input =
let taskX = startTask input
taskX.WhenFinished (fun x ->
let taskY = startAnotherTask x
taskY.WhenFinished (fun y ->
let taskZ = startThirdTask y
taskZ.WhenFinished (fun z ->
do something
let taskExample input =
let taskX = startTask input
taskX.WhenFinished (fun x ->
let taskY = startAnotherTask x
taskY.WhenFinished (fun y ->
do something
let taskExample input =
let taskX = startTask input
taskX.WhenFinished (fun x ->
do something
let whenFinishedDo f task =
task.WhenFinished (fun taskResult ->
f taskResult)
let taskExample input =
startTask input
|> whenFinishedDo startAnotherTask
|> whenFinishedDo startThirdTask
|> whenFinishedDo ...
Parameterize the next step
MONADS!
Is there a general solution to
handling functions like this?
Yes! “Bind” is the answer!
Bind all the things!
How do we compose these?
>> >>
Composing one-track functions is fine...
>> >>
... and composing two-track functions is fine...
 
... but composing points/switches is not allowed!
Two-track input Two-track output
One-track input Two-track output


Two-track input Two-track output
Two-track input Two-track output
A function transformer
let bind nextFunction result =
match result with
| Unhandled n ->
nextFunction n
| Handled str ->
Handled str
Two-track input Two-track output
let bind nextFunction result =
match result with
| Unhandled n ->
nextFunction n
| Handled str ->
Handled str
Two-track input Two-track output
let bind nextFunction result =
match result with
| Unhandled n ->
nextFunction n
| Handled str ->
Handled str
Two-track input Two-track output
let bind nextFunction result =
match result with
| Unhandled n ->
nextFunction n
| Handled str ->
Handled str
Two-track input Two-track output
let bind nextFunction result =
match result with
| Unhandled n ->
nextFunction n
| Handled str ->
Handled str
Two-track input Two-track output
FP terminology
• A monad is
– A data type
– With an associated "bind" function
– (and some other stuff)
• A monadic function is
– A switch/points function
– "bind" is used to compose them
type FizzBuzzResult =
| Unhandled of int
| Handled of string
function AInput Output
function BInput
Output 1
Output 2
Challenge #2: How can we compose these?

KLEISLI COMPOSITION
(WEB SERVICE)
Technique #4
compose
with
Kleisli Composition
Kleisli Composition
Kleisli Composition
Kleisli Composition
=
compose
with
The result is the
same kind of thing
Kleisli Composition
The "Lego" approach to
building a web server
Async<HttpContext option>HttpContext
A HttpHandler "WebPart"
Async<HttpContext option>HttpContext
A HttpHandler "WebPart"
=>=>
The result is another
HttpHandler so you can
keep adding and adding
Composition of HttpHandlers
Kleisli composition symbol
path "/hello"
Checks request path
(might fail)
matches path
doesn't match
OK "Hello"
Sets response
200 OK
path "/hello" >=> OK "Hello"
Checks request path
(might fail)
Sets response
>=>
A new WebPart
choose [
]
Picks first HttpHandler
that succeeds
choose [
path "/hello" >=> OK "Hello"
path "/goodbye" >=> OK "Goodbye"
]
Pick first path
that succeeds
GET
Only succeeds if
request is a GET
GET >=> choose [
path "/hello" >=> OK "Hello"
path "/goodbye" >=> OK "Goodbye"
]
let app = choose [
]
startWebServer defaultConfig app
A complete web app
GET >=> choose [
path "/hello" >=> OK "Hello"
path "/goodbye" >=> OK "Goodbye"
]
POST >=> choose [
path "/hello" >=> OK "Hello POST"
path "/goodbye" >=> OK "Goodbye POST"
]
Http
Response
Http
Request
No classes, no inheritance, one-directional data flow!
Review
• The philosophy of composition
– Connectable,reusable parts
– Building bigger things from smaller things
• FP principles:
– Composable functions
– Composable types
Review
A taste of various composition techniques:
– Piping with "|>"
– Currying/partial application
– Composition using "bind" (monads!)
– Kleisli composition using ">=>"
Don't worry about understanding it all,
but hopefully it's not so scary now!
Why bother?
Benefits of composition:
• Reusable parts – no strings attached
• Testable – parts can be tested in isolation
• Understandable – data flows in one direction
• Maintainable – all dependencies are explicit
• Extendable – can add new parts without touching
old code
• A different way of thinking – it's good for
your brain to learn new things!
Slides and video here
fsharpforfunandprofit.com/composition
Thank you!
@ScottWlaschin Me on twitter
My book

Weitere ähnliche Inhalte

Was ist angesagt?

Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented ProgrammingScott Wlaschin
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Scott Wlaschin
 
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
 
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
 
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
 
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
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Roman Elizarov
 
Monadic Java
Monadic JavaMonadic Java
Monadic JavaMario Fusco
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Philip Schwarz
 
Designing with Capabilities
Designing with CapabilitiesDesigning with Capabilities
Designing with CapabilitiesScott Wlaschin
 
Enterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeEnterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeScott Wlaschin
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlinintelliyole
 
Let's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java APILet's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java APIMario Fusco
 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayDebasish Ghosh
 
Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017Roman Elizarov
 
Kotlin Coroutines in Practice @ KotlinConf 2018
Kotlin Coroutines in Practice @ KotlinConf 2018Kotlin Coroutines in Practice @ KotlinConf 2018
Kotlin Coroutines in Practice @ KotlinConf 2018Roman Elizarov
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Mario Fusco
 
Kotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is comingKotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is comingKirill Rozov
 
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
 
Domain Modeling in a Functional World
Domain Modeling in a Functional WorldDomain Modeling in a Functional World
Domain Modeling in a Functional WorldDebasish Ghosh
 

Was ist angesagt? (20)

Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)
 
The Power Of Composition (DotNext 2019)
The Power Of Composition (DotNext 2019)The Power Of Composition (DotNext 2019)
The Power Of Composition (DotNext 2019)
 
Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)
 
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
 
Domain Modeling Made Functional (KanDDDinsky 2019)
Domain Modeling Made Functional (KanDDDinsky 2019)Domain Modeling Made Functional (KanDDDinsky 2019)
Domain Modeling Made Functional (KanDDDinsky 2019)
 
Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017Deep dive into Coroutines on JVM @ KotlinConf 2017
Deep dive into Coroutines on JVM @ KotlinConf 2017
 
Monadic Java
Monadic JavaMonadic Java
Monadic Java
 
Sequence and Traverse - Part 1
Sequence and Traverse - Part 1Sequence and Traverse - Part 1
Sequence and Traverse - Part 1
 
Designing with Capabilities
Designing with CapabilitiesDesigning with Capabilities
Designing with Capabilities
 
Enterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeEnterprise Tic-Tac-Toe
Enterprise Tic-Tac-Toe
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlin
 
Let's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java APILet's make a contract: the art of designing a Java API
Let's make a contract: the art of designing a Java API
 
Functional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 WayFunctional Domain Modeling - The ZIO 2 Way
Functional Domain Modeling - The ZIO 2 Way
 
Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017
 
Kotlin Coroutines in Practice @ KotlinConf 2018
Kotlin Coroutines in Practice @ KotlinConf 2018Kotlin Coroutines in Practice @ KotlinConf 2018
Kotlin Coroutines in Practice @ KotlinConf 2018
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
 
Kotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is comingKotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is coming
 
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
 
Domain Modeling in a Functional World
Domain Modeling in a Functional WorldDomain Modeling in a Functional World
Domain Modeling in a Functional World
 

Ähnlich wie The Power of Composition (NDC Oslo 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)Scott Wlaschin
 
DISE - Windows Based Application Development in C#
DISE - Windows Based Application Development in C#DISE - Windows Based Application Development in C#
DISE - Windows Based Application Development in C#Rasan Samarasinghe
 
Cucumber
CucumberCucumber
CucumberFarooq Ali
 
DITEC - Programming with C#.NET
DITEC - Programming with C#.NETDITEC - Programming with C#.NET
DITEC - Programming with C#.NETRasan Samarasinghe
 
Think sharp, write swift
Think sharp, write swiftThink sharp, write swift
Think sharp, write swiftPascal Batty
 
F# and Reactive Programming for iOS
F# and Reactive Programming for iOSF# and Reactive Programming for iOS
F# and Reactive Programming for iOSBrad Pillow
 
Type Driven Development with TypeScript
Type Driven Development with TypeScriptType Driven Development with TypeScript
Type Driven Development with TypeScriptGarth Gilmour
 
Functional pogramming hl overview
Functional pogramming hl overviewFunctional pogramming hl overview
Functional pogramming hl overviewElad Avneri
 
Hadoop Streaming Tutorial With Python
Hadoop Streaming Tutorial With PythonHadoop Streaming Tutorial With Python
Hadoop Streaming Tutorial With PythonJoe Stein
 
Programming with python
Programming with pythonProgramming with python
Programming with pythonsarogarage
 
Introduction to C++
Introduction to C++ Introduction to C++
Introduction to C++ Bharat Kalia
 
Five Languages in a Moment
Five Languages in a MomentFive Languages in a Moment
Five Languages in a MomentSergio Gil
 
Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987乐群 陈
 
Extreme Swift
Extreme SwiftExtreme Swift
Extreme SwiftMovel
 
Антон Молдован "Type driven development with f#"
Антон Молдован "Type driven development with f#"Антон Молдован "Type driven development with f#"
Антон Молдован "Type driven development with f#"Fwdays
 
Brixton Library Technology Initiative Week1 Recap
Brixton Library Technology Initiative Week1 RecapBrixton Library Technology Initiative Week1 Recap
Brixton Library Technology Initiative Week1 RecapBasil Bibi
 
The top 5 JavaScript issues in all our codebases
The top 5 JavaScript issues in all our codebasesThe top 5 JavaScript issues in all our codebases
The top 5 JavaScript issues in all our codebasesPhil Nash
 
ppt7
ppt7ppt7
ppt7callroom
 
ppt2
ppt2ppt2
ppt2callroom
 

Ähnlich wie The Power of Composition (NDC Oslo 2020) (20)

Python slide
Python slidePython slide
Python slide
 
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)
 
DISE - Windows Based Application Development in C#
DISE - Windows Based Application Development in C#DISE - Windows Based Application Development in C#
DISE - Windows Based Application Development in C#
 
Cucumber
CucumberCucumber
Cucumber
 
DITEC - Programming with C#.NET
DITEC - Programming with C#.NETDITEC - Programming with C#.NET
DITEC - Programming with C#.NET
 
Think sharp, write swift
Think sharp, write swiftThink sharp, write swift
Think sharp, write swift
 
F# and Reactive Programming for iOS
F# and Reactive Programming for iOSF# and Reactive Programming for iOS
F# and Reactive Programming for iOS
 
Type Driven Development with TypeScript
Type Driven Development with TypeScriptType Driven Development with TypeScript
Type Driven Development with TypeScript
 
Functional pogramming hl overview
Functional pogramming hl overviewFunctional pogramming hl overview
Functional pogramming hl overview
 
Hadoop Streaming Tutorial With Python
Hadoop Streaming Tutorial With PythonHadoop Streaming Tutorial With Python
Hadoop Streaming Tutorial With Python
 
Programming with python
Programming with pythonProgramming with python
Programming with python
 
Introduction to C++
Introduction to C++ Introduction to C++
Introduction to C++
 
Five Languages in a Moment
Five Languages in a MomentFive Languages in a Moment
Five Languages in a Moment
 
Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987
 
Extreme Swift
Extreme SwiftExtreme Swift
Extreme Swift
 
Антон Молдован "Type driven development with f#"
Антон Молдован "Type driven development with f#"Антон Молдован "Type driven development with f#"
Антон Молдован "Type driven development with f#"
 
Brixton Library Technology Initiative Week1 Recap
Brixton Library Technology Initiative Week1 RecapBrixton Library Technology Initiative Week1 Recap
Brixton Library Technology Initiative Week1 Recap
 
The top 5 JavaScript issues in all our codebases
The top 5 JavaScript issues in all our codebasesThe top 5 JavaScript issues in all our codebases
The top 5 JavaScript issues in all our codebases
 
ppt7
ppt7ppt7
ppt7
 
ppt2
ppt2ppt2
ppt2
 

Mehr von 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
 
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
 
Four Languages From Forty Years Ago
Four Languages From Forty Years AgoFour Languages From Forty Years Ago
Four Languages From Forty Years AgoScott Wlaschin
 
F# for C# Programmers
F# for C# ProgrammersF# for C# Programmers
F# for C# ProgrammersScott 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
 
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
 
Dr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterDr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterScott Wlaschin
 
An introduction to property based testing
An introduction to property based testingAn introduction to property based testing
An introduction to property based testingScott Wlaschin
 
Swift vs. Language X
Swift vs. Language XSwift vs. Language X
Swift vs. Language XScott Wlaschin
 
Doge-driven design
Doge-driven designDoge-driven design
Doge-driven designScott Wlaschin
 
The Theory of Chains
The Theory of ChainsThe Theory of Chains
The Theory of ChainsScott Wlaschin
 

Mehr von Scott Wlaschin (12)

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...
 
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)
 
Four Languages From Forty Years Ago
Four Languages From Forty Years AgoFour Languages From Forty Years Ago
Four Languages From Forty Years Ago
 
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)
 
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
 
Dr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterDr Frankenfunctor and the Monadster
Dr Frankenfunctor and the Monadster
 
An introduction to property based testing
An introduction to property based testingAn introduction to property based testing
An introduction to property based testing
 
Swift vs. Language X
Swift vs. Language XSwift vs. Language X
Swift vs. Language X
 
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
 

KĂźrzlich hochgeladen

The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is insideshinachiaurasa2
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxalwaysnagaraju26
 
ManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide DeckManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide DeckManageIQ
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesVictorSzoltysek
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...Jittipong Loespradit
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfayushiqss
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Pharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodologyPharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodologyAnusha Are
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto GonzĂĄlez Trastoy
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...kalichargn70th171
 

KĂźrzlich hochgeladen (20)

The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
 
ManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide DeckManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide Deck
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Pharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodologyPharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodology
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 

The Power of Composition (NDC Oslo 2020)

  • 1. The Power Of Composition NDC Oslo 2020 @ScottWlaschin fsharpforfunandprofit.com
  • 2. The Power Of Composition 1. The philosophy of composition 2. Ideas of functional programming – Functions and how to compose them – Types and how to compose them 3. Composition in practice – Roman Numerals – FizzBuzz gone functional – Uh oh, monads! – A web service
  • 4. Prerequisites for understanding composition • You must have been a child at some point • You must have played with Lego • You must have played with toy trains
  • 6. Lego Philosophy 1. All pieces are designed to be connected 2. The pieces are reusable in many contexts 3. Connect two pieces together and get another "piece" that can still be connected
  • 7. All pieces are designed to be connected
  • 8. The pieces are reusable in different contexts
  • 9. Connect two pieces together and get another "piece" that can still be connected
  • 10. Make big things from small things in the same way
  • 11.
  • 12. Wooden Railway Track Philosophy 1. All pieces are designed to be connected 2. The pieces are reusable in many contexts 3. Connect two pieces together and get another "piece" that can still be connected
  • 13. All pieces are designed to be connected
  • 14. The pieces are reusable in different contexts
  • 15. Connect two pieces together and get another "piece" that can still be connected You can keep adding and adding.
  • 16. Make big things from small things in the same way
  • 17. If you understand Lego and wooden railways, then you know everything about composition!
  • 18. THE IDEAS OF FUNCTIONAL PROGRAMMING
  • 19. Four ideas behind FP Function 3.Types are not classes 1. Functions are things 2. Build bigger functions using composition 4. Build bigger types using composition
  • 20. FP idea #1: Functions are things Function
  • 21. The Tunnel of Transformation Function apple -> banana A function is a thing which transforms inputs to outputs
  • 22. A function is a standalone thing, not attached to a class
  • 23. A function is a standalone thing, not attached to a class It can be used for inputs and outputs of other functions
  • 24. A function can be an output thing input
  • 25. output A function can be an input thing
  • 26. input output A function can be a parameter
  • 28. FP idea #2: Build bigger functions using composition
  • 29. Function 1 apple -> banana Function 2 banana -> cherry
  • 30. >> Function 1 apple -> banana Function 2 banana -> cherry
  • 31. New Function apple -> cherry Can't tell it was built from smaller functions! Where did the banana go?
  • 32. Function composition in F# and C# using the "piping" approach
  • 33. int add1(int x) => x + 1; int times2(int x) => x * 2; int square(int x) => x * x; add1(5); // = 6 times2(add1(5)); // = 12 square(times2(add1(5))); // = 144 Nested function calls can be confusing if too deep
  • 34. add15 6 times2 12 square 144
  • 35. 5 |> add1 // = 6 5 |> add1 |> times2 // = 12 5 |> add1 |> times2 |> square // = 144 add1 times2 square5 6 12 144 F# example
  • 36. add1 times2 square5 6 12 144 5.Pipe(add1); 5.Pipe(add1).Pipe(times2); 5.Pipe(add1).Pipe(times2).Pipe(square); C# example
  • 37. Building big things from functions It's compositions all the way up
  • 39. Low-level operation Service AddressValidator A “Service” is just like a microservice but without the "micro" in front Validation Result Address Low-level operation Low-level operation
  • 42. Http Response Http Request Even for complex applications, data flows only in one direction
  • 43.
  • 44.
  • 45. FP idea #3: Types are not classes
  • 46. So, what is a type then? A type is a just a name for a set of things Set of valid inputs Set of valid outputs Function
  • 47. Set of valid inputs Set of valid outputs Function 1 2 3 4 5 6 This is type "integer" A type is a just a name for a set of things
  • 48. Set of valid inputs Set of valid outputs Function This is type "string" "abc" "but" "cobol" "double" "end" "float" A type is a just a name for a set of things
  • 49. Set of valid inputs Set of valid outputs Function This is type "Person" Donna Roy Javier Mendoza Nathan Logan Shawna Ingram Abel Ortiz Lena Robbins GordonWood A type is a just a name for a set of things
  • 50. Set of valid inputs Set of valid outputs Function This is type "Fruit" A type is a just a name for a set of things
  • 51. Set of valid inputs Set of valid outputs Function This is a type of Fruit->Fruit functions A type is a just a name for a set of things
  • 52. FP idea #4: Types can be composed too
  • 54. Bigger types are built from smaller types by: Composing with “AND” Composing with “OR”
  • 55. FruitSalad = AND AND Compose with “AND”
  • 56. Compose with “AND” enum AppleVariety { Red, Green } enum BananaVariety { Yellow, Brown } enum CherryVariety { Tart, Sweet } struct FruitSalad { AppleVariety Apple; BananaVariety Banana; CherryVariety Cherry; } C# example Apple AND Banana AND Cherry
  • 57. Compose with “AND” type AppleVariety = Red | Green type BananaVariety = Yellow | Brown type CherryVariety = Tart | Sweet type FruitSalad = { Apple: AppleVariety Banana: BananaVariety Cherry: CherryVariety } F# example
  • 58. Snack = OR OR Compose with “OR” type Snack = | Apple of AppleVariety | Banana of BananaVariety | Cherry of CherryVariety
  • 59. A real world example of composing types
  • 60. Some requirements: We accept three forms of payment: Cash, Paypal, or CreditCard. For Cash we don't need any extra information For Paypal we need an email address For Cards we need a card type and card number
  • 61. interface IPaymentMethod {..} class Cash() : IPaymentMethod {..} class Paypal(string emailAddress): IPaymentMethod {..} class Card(string cardType, string cardNo) : IPaymentMethod {..} In OO design you would probably implement it as an interface and a set of subclasses, like this:
  • 62. type EmailAddress = string type CardNumber = string In F# you would probably implement by composing types, like this:
  • 63. type EmailAddress = ... type CardNumber = … type CardType = Visa | Mastercard type CreditCardInfo = { CardType : CardType CardNumber : CardNumber }
  • 64. type EmailAddress = ... type CardNumber = ... type CardType = ... type CreditCardInfo = ... type PaymentMethod = | Cash | PayPal of EmailAddress | Card of CreditCardInfo
  • 65. type EmailAddress = ... type CardNumber = ... type CardType = ... type CreditCardInfo = ... type PaymentMethod = | Cash | PayPal of EmailAddress | Card of CreditCardInfo type PaymentAmount = decimal type Currency = EUR | USD | RUB
  • 66. type EmailAddress = ... type CardNumber = ... type CardType = ... type CreditCardInfo = ... type PaymentMethod = | Cash | PayPal of EmailAddress | Card of CreditCardInfo type PaymentAmount = decimal type Currency = EUR | USD | RUB type Payment = { Amount : PaymentAmount Currency : Currency Method : PaymentMethod }
  • 67. type EmailAddress = ... type CardNumber = ... type CardType = ... type CreditCardInfo = ... type PaymentMethod = | Cash | PayPal of EmailAddress | Card of CreditCardInfo type PaymentAmount = decimal type Currency = EUR | USD | RUB type Payment = { Amount : PaymentAmount Currency : Currency Method : PaymentMethod }
  • 68.
  • 69. Composable types can be used as executable documentation
  • 70. type Deal = Deck -> (Deck * Card) type PickupCard = (Hand * Card) -> Hand type Suit = Club | Diamond | Spade | Heart type Rank = Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | King | Ace type Card = { Suit:Suit; Rank:Rank } type Hand = Card list type Deck = Card list type Player = {Name:string; Hand:Hand} type Game = { Deck:Deck; Players:Player list } The domain on one screen!
  • 71. type CardType = Visa | Mastercard type CardNumber = string type EmailAddress = string type PaymentMethod = | Cash | PayPal of EmailAddress | Card of CreditCardInfo | Bitcoin of BitcoinAddress
  • 72. A big topic and not enough time   More on DDD and designing with types at fsharpforfunandprofit.com/ddd
  • 73. Composition in practice: Time for some real examples!
  • 75. To Roman Numerals • Task: How to convert an arabic integer to roman numerals? • 5 => "V" • 12 => "XII" • 107 => "CVII"
  • 77. To Roman Numerals • Use the "tally" approach – Start with N copies of "I" – Replace five "I"s with a "V" – Replace two "V"s with a "X" – Replace five "X"s with a "L" – Replace two "L"s with a "C" – etc
  • 78. To Roman Numerals number etc Replicate "I" Replace_IIIII_V Replace_VV_X Replace_XXXXX_L
  • 79. string ToRomanNumerals(int number) { // define a helper function for each step string replace_IIIII_V(string s) => s.Replace("IIIII", "V"); string replace_VV_X(string s) => s.Replace("VV", "X"); string replace_XXXXX_L(string s) => s.Replace("XXXXX", "L"); string replace_LL_C(string s) => s.Replace("LL", "C"); // then combine them using piping return new string('I', number) .Pipe(replace_IIIII_V) .Pipe(replace_VV_X) .Pipe(replace_XXXXX_L) .Pipe(replace_LL_C); } C# example
  • 80. let toRomanNumerals number = // define a helper function for each step let replace_IIIII_V str = replace "IIIII" "V" str let replace_VV_X str = replace "VV" "X" str let replace_XXXXX_L str = replace "XXXXX" "L" str let replace_LL_C str = replace "LL" "C" str // then combine them using piping String.replicate number "I" |> replace_IIIII_V |> replace_VV_X |> replace_XXXXX_L |> replace_LL_C F# example
  • 84. function A and B Easy!
  • 85. ... But here is a challenge
  • 86. function AInput Output function B Input 1 Output Input 2
  • 87. function AInput Output function B Input 1 Output Input 2 Challenge #1: How can we compose these? 
  • 88. COMPOSITION WITH CURRYING (ROMAN NUMERALS) Technique #2
  • 89. The Replace function oldValue outputString newValue inputString Replace
  • 90. Uh-oh! Composition problem Replace I / V Replace V / X Replace X / L 
  • 91. Bad news: Composition patterns only work for functions that have one parameter! 
  • 92. Good news! Every function can be turned into a one parameter function 
  • 93. Haskell Curry We named this technique after him
  • 94. Input A Uncurried Function Input B Output C Curried Function Input A Intermediate Function Output CInput B What is currying? after currying Function as output
  • 95. Input A Uncurried Function Input B Output C Curried Function Input A Intermediate Function Output CInput B What is currying? One input One input Currying means that *every* function can be converted to a series of one input functions
  • 97. Replace Old New Old New After currying Func<string,string> replace(string oldVal, string newVal) => input => input.Replace(oldVal, newVal);
  • 98. Replace Old New Old New After currying Func<string,string> replace(string oldVal, string newVal) => input => input.Replace(oldVal, newVal);
  • 99. Func<string,string> replace(string oldVal, string newVal) => input => input.Replace(oldVal, newVal); Replace Old New Old New After currying This lambda (function) is returned one-parameter function
  • 100. string ToRomanNumerals(int number) { // define a general helper function Func<string,string> replace( string oldValue, string newValue) => input => input.Replace(oldValue, newValue); // then use piping return new string('I', number) .Pipe(replace("IIIII","V")) .Pipe(replace("VV","X")) .Pipe(replace("XXXXX","L")) .Pipe(replace("LL","C")); } C# example
  • 101. string ToRomanNumerals(int number) { // define a general helper function Func<string,string> replace( string oldValue, string newValue) => input => input.Replace(oldValue, newValue); // then use piping return new string('I', number) .Pipe(replace("IIIII","V")) .Pipe(replace("VV","X")) .Pipe(replace("XXXXX","L")) .Pipe(replace("LL","C")); } C# example
  • 102. string ToRomanNumerals(int number) { // define a general helper function Func<string,string> replace( string oldValue, string newValue) => input => input.Replace(oldValue, newValue); // then use piping return new string('I', number) .Pipe(replace("IIIII","V")) .Pipe(replace("VV","X")) .Pipe(replace("XXXXX","L")) .Pipe(replace("LL","C")); } C# example Only 2 of the 3 parameters are passed in The other parameter comes from the pipeline
  • 103. let toRomanNumerals number = // no helper function needed. // currying occurs automatically in F# // combine using piping String.replicate number "I" |> replace "IIIII" "V" |> replace "VV" "X" |> replace "XXXXX" "L" |> replace "LL" "C" F# example
  • 104. let toRomanNumerals number = // no helper function needed. // currying occurs automatically in F# // combine using piping String.replicate number "I" |> replace "IIIII" "V" |> replace "VV" "X" |> replace "XXXXX" "L" |> replace "LL" "C" Only 2 of the 3 parameters are passed in F# example The other parameter comes from the pipeline
  • 106. Partial Application let add x y = x + y let multiply x y = x * y 5 |> add 2 |> multiply 3 Piping provides the missing argument partial application
  • 107. Partial Application Replace ReplaceOldNew Old New Old New String.replicate number "I" |> replace "IIIII" "V" |> replace "VV" "X" |> replace "XXXXX" "L" |> replace "LL" "C" Only 2 parameters passed in Piping provides the missing argument
  • 109. let toRomanNumerals number = String.replicate number "I" |> replace "IIIII" "V" |> replace "VV" "X" |> replace "XXXXX" "L" |> replace "LL" "C" Composable => extensible // can easily add new segments to the pipeline |> replace "VIIII" "IX" |> replace "IIII" "IV" |> replace "LXXXX" "XC"
  • 110. functionInput Output function Input 1 Output Input 2 Challenge #1: How can we compose these? 
  • 111. Here is another challenge
  • 112. function AInput Output function BInput Output 1 Output 2
  • 113. function AInput Output function BInput Output 1 Output 2 Challenge #2: How can we compose these? 
  • 115. FizzBuzz definition Write a program that takes a number as input • For multiples of three print "Fizz" • For multiples of five print "Buzz" • For multiples of both three and five print "FizzBuzz" • Otherwise, print the original number
  • 116. let fizzBuzz n = if (isDivisibleBy n 15) then printfn "FizzBuzz" else if (isDivisibleBy n 3) then printfn "Fizz" else if (isDivisibleBy n 5) then printfn "Buzz" else printfn "%i" n let isDivisibleBy n divisor = (n % divisor) = 0 // helper function A simple F# implementation
  • 117. let fizzBuzz n = if (isDivisibleBy n 15) then printfn "FizzBuzz" else if (isDivisibleBy n 3) then printfn "Fizz" else if (isDivisibleBy n 5) then printfn "Buzz" else printfn "%i" n let isDivisibleBy n divisor = (n % divisor) = 0 // helper function A simple F# implementation
  • 119. Pipeline implementation Handle 3 case number Handle 15 case
  • 120. Pipeline implementation Handle 3 case Handle 5 case number Handle 15 case
  • 121. Pipeline implementation Handle 3 case Handle 5 case number Answer Handle 15 case Last step
  • 122. number Handle case Handled (e.g. "Fizz", "Buzz") Unhandled (e.g. 2, 7, 13)
  • 124. Unhandled Handled Input -> type FizzBuzzResult = | Unhandled of int // the original int | Handled of string // "Fizz", Buzz", etc Idea from http://weblog.raganwald.com/2007/01/dont-overthink-fizzbuzz.html or
  • 125. type FizzBuzzResult = | Unhandled of int // the original int | Handled of string // "Fizz", Buzz", etc let handle divisor label n = if (isDivisibleBy n divisor) then Handled label else Unhandled n Idea from http://weblog.raganwald.com/2007/01/dont-overthink-fizzbuzz.html
  • 126. type FizzBuzzResult = | Unhandled of int // the original int | Handled of string // "Fizz", Buzz", etc let handle divisor label n = if (isDivisibleBy n divisor) then Handled label else Unhandled n
  • 127. 12 |> handle 3 "Fizz" // Handled "Fizz" 10 |> handle 3 "Fizz" // Unhandled 10 10 |> handle 5 "Buzz" // Handled "Buzz" handle 5 "Buzz"
  • 128. let fizzbuzz n = let result15 = n |> handle 15 "FizzBuzz" match result15 with | Handled str -> str | Unhandled n -> let result3 = n |> handle 3 "Fizz" match result3 with | Handled str -> str | Unhandled n -> let result5 = n |> handle 5 "Buzz" match result5 with | Handled str -> str | Unhandled n -> string n // convert to string First implementation attempt
  • 129. let fizzbuzz n = let result15 = n |> handle 15 "FizzBuzz" match result15 with | Handled str -> str | Unhandled n -> let result3 = n |> handle 3 "Fizz" match result3 with | Handled str -> str | Unhandled n -> let result5 = n |> handle 5 "Buzz" match result5 with | Handled str -> str | Unhandled n -> // do something with Unhandled value
  • 130. let fizzbuzz n = let result15 = n |> handle 15 "FizzBuzz" match result15 with | Handled str -> str | Unhandled n -> let result3 = n |> handle 3 "Fizz" match result3 with | Handled str -> str | Unhandled n -> // do something with Unhandled value // ... // ...
  • 131. let fizzbuzz n = let result15 = n |> handle 15 "FizzBuzz" match result15 with | Handled str -> str | Unhandled n -> // do something with Unhandled value // ... // ...
  • 132. if Handled then // return the string if Unhandled then // do something with the number
  • 133. If Unhandled If Handled Bypass and return the string
  • 134. let ifUnhandledDo f result = match result with | Handled str -> Handled str | Unhandled n -> f n
  • 135. let fizzbuzz n = n |> handle 15 "FizzBuzz" |> ifUnhandledDo (handle 3 "Fizz") |> ifUnhandledDo (handle 5 "Buzz") |> lastStep
  • 136. let fizzbuzz n = n |> handle 15 "FizzBuzz" |> ifUnhandledDo (handle 3 "Fizz") |> ifUnhandledDo (handle 5 "Buzz") |> lastStep
  • 137. let fizzbuzz n = n |> handle 15 "FizzBuzz" |> ifUnhandledDo (handle 3 "Fizz") |> ifUnhandledDo (handle 5 "Buzz") |> lastStep
  • 138. let fizzbuzz n = n |> handle 15 "FizzBuzz" |> ifUnhandledDo (handle 3 "Fizz") |> ifUnhandledDo (handle 5 "Buzz") |> lastStep
  • 139. let fizzbuzz n = n |> handle 15 "FizzBuzz" |> ifUnhandledDo (handle 3 "Fizz") |> ifUnhandledDo (handle 5 "Buzz") |> lastStep let lastStep result = match result with | Handled str -> str | Unhandled n -> string(n) // convert to string
  • 140. let fizzbuzz n = n |> handle 15 "FizzBuzz" |> ifUnhandledDo (handle 3 "Fizz") |> ifUnhandledDo (handle 5 "Buzz") |> lastStep Composable => easy to extend
  • 141. let fizzbuzz n = n |> handle 15 "FizzBuzz" |> ifUnhandledDo (handle 3 "Fizz") |> ifUnhandledDo (handle 5 "Buzz") |> ifUnhandledDo (handle 7 "Baz") |> lastStep Composable => easy to extend
  • 142. let fizzbuzz n = n |> handle 15 "FizzBuzz" |> ifUnhandledDo (handle 3 "Fizz") |> ifUnhandledDo (handle 5 "Buzz") |> ifUnhandledDo (handle 7 "Baz") |> ifUnhandledDo (handle 11 "Pozz") |> lastStep Composable => easy to extend
  • 143. let fizzbuzz n = n |> handle 15 "FizzBuzz" |> ifUnhandledDo (handle 3 "Fizz") |> ifUnhandledDo (handle 5 "Buzz") |> ifUnhandledDo (handle 7 "Baz") |> ifUnhandledDo (handle 11 "Pozz") |> ifUnhandledDo (handle 13 "Tazz") |> lastStep Composable => easy to extend
  • 145. When task completesWait Wait a.k.a "promise", "future"
  • 146. let taskExample input = let taskX = startTask input taskX.WhenFinished (fun x -> let taskY = startAnotherTask x taskY.WhenFinished (fun y -> let taskZ = startThirdTask y taskZ.WhenFinished (fun z -> etc
  • 147. let taskExample input = let taskX = startTask input taskX.WhenFinished (fun x -> let taskY = startAnotherTask x taskY.WhenFinished (fun y -> let taskZ = startThirdTask y taskZ.WhenFinished (fun z -> do something
  • 148. let taskExample input = let taskX = startTask input taskX.WhenFinished (fun x -> let taskY = startAnotherTask x taskY.WhenFinished (fun y -> do something
  • 149. let taskExample input = let taskX = startTask input taskX.WhenFinished (fun x -> do something
  • 150. let whenFinishedDo f task = task.WhenFinished (fun taskResult -> f taskResult) let taskExample input = startTask input |> whenFinishedDo startAnotherTask |> whenFinishedDo startThirdTask |> whenFinishedDo ... Parameterize the next step
  • 152. Is there a general solution to handling functions like this?
  • 153. Yes! “Bind” is the answer! Bind all the things!
  • 154. How do we compose these?
  • 155.
  • 156. >> >> Composing one-track functions is fine...
  • 157. >> >> ... and composing two-track functions is fine...
  • 158.   ... but composing points/switches is not allowed!
  • 159. Two-track input Two-track output One-track input Two-track output  
  • 161. Two-track input Two-track output A function transformer
  • 162. let bind nextFunction result = match result with | Unhandled n -> nextFunction n | Handled str -> Handled str Two-track input Two-track output
  • 163. let bind nextFunction result = match result with | Unhandled n -> nextFunction n | Handled str -> Handled str Two-track input Two-track output
  • 164. let bind nextFunction result = match result with | Unhandled n -> nextFunction n | Handled str -> Handled str Two-track input Two-track output
  • 165. let bind nextFunction result = match result with | Unhandled n -> nextFunction n | Handled str -> Handled str Two-track input Two-track output
  • 166. let bind nextFunction result = match result with | Unhandled n -> nextFunction n | Handled str -> Handled str Two-track input Two-track output
  • 167. FP terminology • A monad is – A data type – With an associated "bind" function – (and some other stuff) • A monadic function is – A switch/points function – "bind" is used to compose them type FizzBuzzResult = | Unhandled of int | Handled of string
  • 168. function AInput Output function BInput Output 1 Output 2 Challenge #2: How can we compose these? 
  • 174. = compose with The result is the same kind of thing Kleisli Composition
  • 175. The "Lego" approach to building a web server
  • 178. =>=> The result is another HttpHandler so you can keep adding and adding Composition of HttpHandlers Kleisli composition symbol
  • 179. path "/hello" Checks request path (might fail) matches path doesn't match
  • 181. path "/hello" >=> OK "Hello" Checks request path (might fail) Sets response >=> A new WebPart
  • 182. choose [ ] Picks first HttpHandler that succeeds
  • 183. choose [ path "/hello" >=> OK "Hello" path "/goodbye" >=> OK "Goodbye" ] Pick first path that succeeds
  • 185. GET >=> choose [ path "/hello" >=> OK "Hello" path "/goodbye" >=> OK "Goodbye" ]
  • 186. let app = choose [ ] startWebServer defaultConfig app A complete web app GET >=> choose [ path "/hello" >=> OK "Hello" path "/goodbye" >=> OK "Goodbye" ] POST >=> choose [ path "/hello" >=> OK "Hello POST" path "/goodbye" >=> OK "Goodbye POST" ]
  • 187. Http Response Http Request No classes, no inheritance, one-directional data flow!
  • 188. Review • The philosophy of composition – Connectable,reusable parts – Building bigger things from smaller things • FP principles: – Composable functions – Composable types
  • 189. Review A taste of various composition techniques: – Piping with "|>" – Currying/partial application – Composition using "bind" (monads!) – Kleisli composition using ">=>" Don't worry about understanding it all, but hopefully it's not so scary now!
  • 190. Why bother? Benefits of composition: • Reusable parts – no strings attached • Testable – parts can be tested in isolation • Understandable – data flows in one direction • Maintainable – all dependencies are explicit • Extendable – can add new parts without touching old code • A different way of thinking – it's good for your brain to learn new things!
  • 191. Slides and video here fsharpforfunandprofit.com/composition Thank you! @ScottWlaschin Me on twitter My book