SlideShare une entreprise Scribd logo
1  sur  202
Télécharger pour lire hors ligne
Functional Design Patterns
@ScottWlaschin
fsharpforfunandprofit.com
DevTernity 2018 Edition
This talk
A whirlwind tour of many sights
Don't worry if you don't understand everything
HOW I GOT HERE
Me
I've been programming a long time
I used to be a normal programmer...
And then I was introduced to some
functional programmers…
https://www.flickr.com/photos/37511372@N08/5488671752/
Haskell programmers
F#/OCaml programmers
Visual Basic programmers
Lisp
programmers
Now I can say this with a straight face:
“A monad is just a monoid in the
category of endofunctors,
what’s the problem?”
FP DESIGN PATTERNS
• Single Responsibility Principle
• Open/Closed principle
• Dependency Inversion
Principle
• Interface Segregation
Principle
• Factory pattern
• Strategy pattern
• Decorator pattern
• Visitor pattern
OO pattern/principle
• Single Responsibility Principle
• Open/Closed principle
• Dependency Inversion
Principle
• Interface Segregation
Principle
• Factory pattern
• Strategy pattern
• Decorator pattern
• Visitor pattern
OO pattern/principle Borg response
• Single Responsibility Principle
• Open/Closed principle
• Dependency Inversion
Principle
• Interface Segregation
Principle
• Factory pattern
• Strategy pattern
• Decorator pattern
• Visitor pattern
• Functions
• Functions
• Functions, also
• Functions
• You will be assimilated!
• Functions again
• Functions
• Resistance is futile!
OO pattern/principle FP equivalent
Seriously, FP patterns are different
Overview
• 3 Core Principles of FP design
• Pattern 1: Functions as parameters
• Pattern 2: Composing multi-parameter functions
• Pattern 3: "bind"
• Pattern 4: "map"
• Pattern 5: Monoids
THREE CORE PRINCIPLES OF
FUNCTIONAL PROGRAMMING
There are more...
Core principles of FP
Function
Types are not classes
Functions are things
Composition everywhere
Core principle:
Functions are things
Function
The Tunnel of
Transformation
Function
apple -> banana
A function is a standalone thing,
not attached to a class
let z = 1 1
let addOne x = x + 1 int-> int
int->(int->int)int int->int
Function as output
intInt ->int
Function as input
(int->int)->int
int int
Function as parameterint->int
int->int
Core principle:
Composition everywhere
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?
Composition works at all scales
Low-level operation
ToUpper
stringstring
Low-level operation
Service
AddressValidator
For those under 30...
Validation
Result
Address
Low-level operation Low-level operation
a "service" is just like a microservice
but without the "micro" in front
Service
Use-case
UpdateProfileData
ChangeProfile
Result
ChangeProfile
Request
Service Service
Use-case
Web application
Http
Response
Http
Request
Use-case Use-case
Core principle:
Types are not classes
So, what is a type then?
Set of
valid inputs
Function
Set of
valid outputs
Function
Set of
valid inputs
Set of
valid outputs
Function
A type is a just a name
for a set of things
Set of
valid inputs
Set of
valid outputs
Function
1
2
3
4
5
6
This is type
"integer"
Set of
valid inputs
Set of
valid outputs
Function
This is type
"string"
"abc"
"but"
"cobol"
"double"
"end"
"float"
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
Set of
valid inputs
Set of
valid outputs
Function
This is type
"Fruit"
Set of
valid inputs
Set of
valid outputs
Function
This is a type of
Fruit->Fruit functions
Composition everywhere:
Types can be composed too
"Algebraic type system"
"Composable type system"
New types are built from smaller types by:
Composing with “AND”
Composing with “OR”
Example: tuples, structs, records
FruitSalad = One each of and and
“AND” types (Record types)
type FruitSalad = {
Apple: AppleVariety
Banana: BananaVariety
Cherry: CherryVariety
}
Snack = or or
“OR” types (Choice types)
type Snack =
| Apple of AppleVariety
| Banana of BananaVariety
| Cherry of CherryVariety
Real world example
of type composition
Example of some requirements:
We accept three forms of payment:
Cash, Check, or Card.
For Cash we don't need any extra information
For Checks we need a check number
For Cards we need a card type and card number
interface IPaymentMethod
{..}
class Cash() : IPaymentMethod
{..}
class Check(int checkNo): IPaymentMethod
{..}
class Card(string cardType, string cardNo) : IPaymentMethod
{..}
In OOP you would probably implement it as an
interface and a set of subclasses, like this:
type CheckNumber = int
type CardNumber = string
In FP you would probably implement by composing
types, like this:
type CheckNumber = ...
type CardNumber = …
type CardType = Visa | Mastercard
type CreditCardInfo = {
CardType : CardType
CardNumber : CardNumber
}
type CheckNumber = ...
type CardNumber = ...
type CardType = ...
type CreditCardInfo = ...
type PaymentMethod =
| Cash
| Check of CheckNumber
| Card of CreditCardInfo
type CheckNumber = ...
type CardNumber = ...
type CardType = ...
type CreditCardInfo = ...
type PaymentMethod =
| Cash
| Check of CheckNumber
| Card of CreditCardInfo
type PaymentAmount = decimal
type Currency = EUR | USD
type CheckNumber = ...
type CardNumber = ...
type CardType = ...
type CreditCardInfo = ...
type PaymentMethod =
| Cash
| Check of CheckNumber
| Card of CreditCardInfo
type PaymentAmount = decimal
type Currency = EUR | USD
type Payment = {
Amount : PaymentAmount
Currency: Currency
Method: PaymentMethod }
type CheckNumber = int
type CardNumber = string
type CardType = Visa | Mastercard
type CreditCardInfo = CardType * CardNumber
type PaymentMethod =
| Cash
| Check of CheckNumber
| Card of CreditCardInfo
type PaymentAmount = decimal
type Currency = EUR | USD
type Payment = {
Amount : PaymentAmount
Currency: Currency
Method: PaymentMethod }
Design principle:
Use static types for domain
modelling and documentation
Static types only!
Sorry Clojure and JS
developers 
A big topic and not enough time  
More on DDD and designing with types at
fsharpforfunandprofit.com/ddd
PATTERN 1:
FUNCTIONS AS PARAMETERS
Guideline:
Parameterize all the things
let printList() =
for i in [1..10] do
printfn "the number is %i" i
So parameterize the data
let printList aList =
for i in aList do
printfn "the number is %i" i
let printList aList =
for i in aList do
printfn "the number is %i" i
let printList anAction aList =
for i in aList do
anAction i
So parameterize the action as well:
We've decoupled the
behavior from the data.
Any list, any action!
C# parameterization example
public static int Product(int n)
{
int product = 1;
for (int i = 1; i <= n; i++)
{
product *= i;
}
return product;
}
public static int Sum(int n)
{
int sum = 0;
for (int i = 1; i <= n; i++)
{
sum += i;
}
return sum;
}
public static int Product(int n)
{
int product = 1;
for (int i = 1; i <= n; i++)
{
product *= i;
}
return product;
}
public static int Sum(int n)
{
int sum = 0;
for (int i = 1; i <= n; i++)
{
sum += i;
}
return sum;
}
public static int Product(int n)
{
int product = 1;
for (int i = 1; i <= n; i++)
{
product *= i;
}
return product;
}
public static int Sum(int n)
{
int sum = 0;
for (int i = 1; i <= n; i++)
{
sum += i;
}
return sum;
}
After parameterization
public static int Aggregate(
int initialValue,
Func<int,int,int> action,
int n)
{
int totalSoFar = initialValue;
for (int i = 1; i <= n; i++)
{
totalSoFar = action(totalSoFar,i);
}
return totalSoFar;
}
Tip:
Function types are "interfaces"
interface IBunchOfMethods
{
int DoSomething(int x);
string DoSomethingElse(int x);
void DoAThirdThing(string x);
}
Let's take the
Single Responsibility Principle and the
Interface Segregation Principle
to the extreme...
Every interface should have
only one method!
interface IBunchOfMethods
{
int DoSomething(int x);
}
An interface with one method is a just a function type
type DoSomething: int -> int
type DoSomething: int -> int
*Any* function with that type is compatible with it
let add2 x = x + 2 // int -> int
let times3 x = x * 3 // int -> int
No interface declaration needed!
Example:
Decorator pattern
let isEven x = ... // int -> bool
isEvenint bool
Log the input Log the output
let isEven x = ... // int -> bool
isEvenint bool
isEvenint boollogint int logbool bool
Compose!
let isEven x = ... // int -> bool
isEvenint bool
logint log boolisEven
let isEven x = ... // int -> bool
isEvenint bool
int log bool
let isEvenWithLogging = // int -> bool
Substitutable for original isEven
isEvenWithLogging
Tip:
"Use interfaces for loose coupling"
Use function parameters for loose coupling
PATTERN 2:
COMPOSING MULTI-PARAMETER FUNCTIONS
Bad news:
Composition patterns
only work for functions that
have one parameter! 
Good news!
Every function can be turned into a
one parameter function 
let add x y = x + y
let add = (fun x y -> x + y)
let add x = (fun y -> x + y)
int-> int->int
int-> int->int
int-> (int->int)
Normal function (Two parameters)
let add x y = x + y
let add = (fun x y -> x + y)
let add x = (fun y -> x + y)
int-> int->int
int-> int->int
int-> (int->int)
Pattern:
Partial application
let name = "Scott"
printfn "Hello, my name is %s" name
let name = "Scott"
(printfn "Hello, my name is %s") name
let hello = (printfn "Hello, my name is %s")
Can reuse "hello" in many places now!
let name = "Scott"
hello name
let name = "Alice"
hello name
Example:
Partial application with lists
let names = ["Alice"; "Bob"; "Scott"]
List.iter hello names //foreach name in names
let hello = printfn "Hello, my name is %s"
let add1 = (+) 1
let equals2 = (=) 2
[1..100]
|> List.map add1
|> List.filter equals2
PATTERN 3
"BIND"
Taming the "pyramid of doom"
let example input =
let x = doSomething input
if x <> null then
let y = doSomethingElse x
if y <> null then
let z = doAThirdThing y
if z <> null then
let result = z
result
else
null
else
null
else
null
I know you could do early
returns, but bear with me...
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 ->
z // final result
)
)
)
let example input =
let x = doSomething input
if x <> null then
let y = doSomethingElse x
if y <> null then
let z = doAThirdThing y
if z <> null then
let result = z
result
else
null
else
null
else
null
Nulls are a code smell:
replace with Option!
Let's fix this!
let example input =
let x = doSomething input
if x.IsSome then
let y = doSomethingElse (x.Value)
if y.IsSome then
let z = doAThirdThing (y.Value)
if z.IsSome then
let result = z.Value
Some result
else
None
else
None
else
None
Much more elegant, yes?
No! This is fugly!
But there is a pattern we can exploit...
let example input =
let x = doSomething input
if x.IsSome then
let y = doSomethingElse (x.Value)
if y.IsSome then
let z = doAThirdThing (y.Value)
if z.IsSome then
// do something with z.Value
// in this block
else
None
else
None
else
None
let example input =
let x = doSomething input
if x.IsSome then
let y = doSomethingElse (x.Value)
if y.IsSome then
// do something with y.Value
// in this block
else
None
else
None
let example input =
let x = doSomething input
if x.IsSome then
// do something with x.Value
// in this block
else
None
Can you see the pattern?
if opt.IsSome then
//do something with opt.Value
else
None
let ifSomeDo f opt =
if opt.IsSome then
f opt.Value
else
None
let example input =
doSomething input
|> ifSomeDo doSomethingElse
|> ifSomeDo doAThirdThing
|> ifSomeDo ...
let ifSomeDo f opt =
if opt.IsSome then
f opt.Value
else
None
Some
None
Input ->
This is an example of a more general problem
on Some
Bypass on None
>> >>
Composing one-track functions is fine...
>> >>
... and composing two-track functions is fine...
 
... but composing switches is not allowed!
How to combine the
mismatched functions?
“Bind” is the answer!
Bind all the things!
Two-track input Two-track input
One-track input Two-track input


Two-track input
Slot for switch function
Two-track output
Two-track input Two-track output
let bind nextFunction optionInput =
match optionInput with
| Some s -> nextFunction s
| None -> None
Two-track input Two-track output
let bind nextFunction optionInput =
match optionInput with
| Some s -> nextFunction s
| None -> None
Two-track input Two-track output
let bind nextFunction optionInput =
match optionInput with
| Some s -> nextFunction s
| None -> None
Two-track input Two-track output
let bind nextFunction optionInput =
match optionInput with
| Some s -> nextFunction s
| None -> None
Two-track input Two-track output
Pattern:
Use bind to chain options
let example input =
let x = doSomething input
if x.IsSome then
let y = doSomethingElse (x.Value)
if y.IsSome then
let z = doAThirdThing (y.Value)
if z.IsSome then
let result = z.Value
Some result
else
None
else
None
else
None
Before
let bind f opt =
match opt with
| Some v -> f v
| None -> None
After
let example input =
doSomething input
|> bind doSomethingElse
|> bind doAThirdThing
|> bind ...
let bind f opt =
match opt with
| Some v -> f v
| None -> None
No pyramids!
Code is linear and clear.
This pattern is called “monadic bind”
After
Pattern:
Use bind to chain tasks
a.k.a "promise" "future"
When task
completesWait Wait
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 ->
z // final result
)
)
)
Before
let taskBind f task =
task.WhenFinished (fun taskResult ->
f taskResult)
let taskExample input =
startTask input
|> taskBind startAnotherTask
|> taskBind startThirdTask
|> taskBind ...
This pattern is also a “monadic bind”
After
Pattern:
Use bind to chain error handlers
string UpdateCustomerWithErrorHandling()
{
var request = receiveRequest();
validateRequest(request);
canonicalizeEmail(request);
db.updateDbFromRequest(request);
smtpServer.sendEmail(request.Email)
return "OK";
}
string UpdateCustomerWithErrorHandling()
{
var request = receiveRequest();
var isValidated = validateRequest(request);
if (!isValidated) {
return "Request is not valid"
}
canonicalizeEmail(request);
db.updateDbFromRequest(request);
smtpServer.sendEmail(request.Email)
return "OK";
}
string UpdateCustomerWithErrorHandling()
{
var request = receiveRequest();
var isValidated = validateRequest(request);
if (!isValidated) {
return "Request is not valid"
}
canonicalizeEmail(request);
var result = db.updateDbFromRequest(request);
if (!result) {
return "Customer record not found"
}
smtpServer.sendEmail(request.Email)
return "OK";
}
string UpdateCustomerWithErrorHandling()
{
var request = receiveRequest();
var isValidated = validateRequest(request);
if (!isValidated) {
return "Request is not valid"
}
canonicalizeEmail(request);
try {
var result = db.updateDbFromRequest(request);
if (!result) {
return "Customer record not found"
}
} catch {
return "DB error: Customer record not updated"
}
smtpServer.sendEmail(request.Email)
return "OK";
}
string UpdateCustomerWithErrorHandling()
{
var request = receiveRequest();
var isValidated = validateRequest(request);
if (!isValidated) {
return "Request is not valid"
}
canonicalizeEmail(request);
try {
var result = db.updateDbFromRequest(request);
if (!result) {
return "Customer record not found"
}
} catch {
return "DB error: Customer record not updated"
}
if (!smtpServer.sendEmail(request.Email)) {
log.Error "Customer email not sent"
}
return "OK";
}
string UpdateCustomerWithErrorHandling()
{
var request = receiveRequest();
var isValidated = validateRequest(request);
if (!isValidated) {
return "Request is not valid"
}
canonicalizeEmail(request);
try {
var result = db.updateDbFromRequest(request);
if (!result) {
return "Customer record not found"
}
} catch {
return "DB error: Customer record not updated"
}
if (!smtpServer.sendEmail(request.Email)) {
log.Error "Customer email not sent"
}
return "OK";
}
Tip:
Use a Result type for error handling
Request SuccessValidate
Failure
type Result =
| Ok of SuccessValue
| Error of ErrorValue
Define a choice type
Request SuccessValidate
Failure
let validateInput input =
if input.name = "" then
Error "Name must not be blank"
else if input.email = "" then
Error "Email must not be blank"
else
Ok input // happy path
Validate UpdateDb SendEmail
Validate UpdateDb SendEmail
Functional flow without error handling
let updateCustomer =
receiveRequest()
|> validateRequest
|> canonicalizeEmail
|> updateDbFromRequest
|> sendEmail
|> returnMessage
Before
One track
let updateCustomerWithErrorHandling =
receiveRequest()
|> validateRequest
|> canonicalizeEmail
|> updateDbFromRequest
|> sendEmail
|> returnMessage
Functional flow with error handling
After
Two track
FP terminology
• A monad is
– A data type
– With an associated bind/flatMap function (and
some other stuff)
– With a sensible implementation (monad laws).
• A monadic function is
– A switch/points function
– bind/flatMap is used to compose them
Tip:
Monads are a general purpose way
of composing functions with
complex outputs
PATTERN 4
"MAP"
World of normal values
int string bool
World of options
Option<int> Option<string> Option<bool>
World of options
World of normal values
int string bool
Option<int> Option<string> Option<bool>

World of options
World of normal values
Option<int> Option<string> Option<bool>

int string bool
let add42 x = x + 42
add42 1 // 43
let add42ToOption opt =
if opt.IsSome then
let newVal = add42 opt.Value
Some newVal
else
None 
World of options
World of normal values
add42 
World of options
World of normal values
add42
World of options
World of normal values
option -> -> option
Option.map
let add42 x = x + 42
add42 1 // 43
let add42ToOption = Option.map add42
add42ToOption (Some 1) // Some 43

World of lists
World of normal values
List.map
list-> -> list
let add42ToEach = List.map add42
add42ToEach [1;2;3] // [43;44;45]
World of async
World of normal values
async<T> -> -> async<U>
Async.map
Guideline:
Most wrapped generic types
have a “map”. Use it!
Guideline:
If you create your own generic type,
create a “map” for it.
FP terminology
• A functor is
– A data type
– With an associated "map" function
(with a sensible implementation)
PATTERN 5:
MONOIDS
Mathematics
Ahead
1 + 2 = 3
1 + (2 + 3) = (1 + 2) + 3
1 + 0 = 1
0 + 1 = 1
1 + 2 = 3
Some things
A way of combining
them
2 x 3 = 6
Some things
A way of combining
them
"a" + "b" = "ab"
Some things
A way of combining
them
concat([a],[b]) = [a; b]
Some things
A way of combining
them
1 + 2
1 + 2 + 3
1 + 2 + 3 + 4
Is an integer
Is an integer
A pairwise operation has
become an operation that
works on lists!
1 + (2 + 3) = (1 + 2) + 3
Order of combining doesn’t matter
1 + 2 + 3 + 4
(1 + 2) + (3 + 4)
((1 + 2) + 3) + 4
All the same
1 - (2 - 3) = (1 - 2) - 3
Order of combining does matter
1 + 0 = 1
0 + 1 = 1
A special kind of thing that when
you combine it with something, just
gives you back the original
something
42 * 1 = 42
1 * 42 = 42
A special kind of thing that when
you combine it with something, just
gives you back the original
something
"" + "hello" = "hello"
"hello" + "" = "hello"
“Zero” for strings
• You start with a bunch of things, and some way of
combining them two at a time.
• Rule 1 (Closure):The result of combining two things is
always another one of the things.
• Rule 2 (Associativity):When combining more than
two things, which pairwise combination you do first
doesn't matter.
• Rule 3 (Identity element):There is a special thing
called "zero" such that when you combine any thing
with "zero" you get the original thing back. A monoid!
• Rule 1 (Closure):The result of combining two
things is always another one of the things.
• Benefit: converts pairwise operations into
operations that work on lists.
1 + 2 + 3 + 4
[ 1; 2; 3; 4 ] |> List.reduce (+)
We'll see
this a lot!
1 * 2 * 3 * 4
[ 1; 2; 3; 4 ] |> List.reduce (*)
• Rule 1 (Closure):The result of combining two
things is always another one of the things.
• Benefit: converts pairwise operations into
operations that work on lists.
"a" + "b" + "c" + "d"
[ "a"; "b"; "c"; "d" ] |> List.reduce (+)
• Rule 1 (Closure):The result of combining two
things is always another one of the things.
• Benefit: converts pairwise operations into
operations that work on lists.
• Rule 2 (Associativity):When combining more
than two things, which pairwise combination
you do first doesn't matter.
• Benefit: Divide and conquer, parallelization, and
incremental accumulation.
Parallelization:
1 + 2 + 3 + 4
Parallelization:
(1 + 2) (3 + 4)
3 + 7
• Rule 2 (Associativity):When combining more
than two things, which pairwise combination
you do first doesn't matter.
• Benefit: Divide and conquer, parallelization, and
incremental accumulation.
Incremental accumulation
(1 + 2 + 3)
Incremental accumulation
(1 + 2 + 3) + 4
Incremental accumulation
(6) + 4
• How can I use reduce on an empty list?
• In a divide and conquer algorithm, what should I
do if one of the "divide" steps has nothing in it?
• When using an incremental algorithm, what
value should I start with when I have no data?
• Rule 3 (Identity element):There is a special
thing called "zero" such that when you combine
any thing with "zero" you get the original thing
back.
• Benefit: Initial value for empty or missing data
Tip:
Simplify aggregation code with monoids
type OrderLine = {Qty:int; Total:float}
let orderLines = [
{Qty=2; Total=19.98}
{Qty=1; Total= 1.99}
{Qty=3; Total= 3.99} ]
How to add them up?
type OrderLine = {Qty:int; Total:float}
let addPair line1 line2 =
let newQty = line1.Qty + line2.Qty
let newTotal = line1.Total + line2.Total
{Qty=newQty; Total=newTotal}
orderLines |> List.reduce addPair
// {Qty=6; Total= 25.96}
Any combination
of monoids is
also a monoid
Write a pairwise combiner
Profit!
Pattern:
Convert non-monoids to monoids
Customer
+
Customer
+
Customer
Customer Stats
+
Customer Stats
+
Customer Stats
Reduce
Map
Not a monoid A monoid
Customer Stats
(Total)
Hadoop make me a sandwich
https://twitter.com/daviottenheimer
/status/532661754820829185
Pattern:
Seeing monoids everywhere
Monoids in the real world
Metrics guideline:
Use counters rather than rates
Alternative metrics guideline:
Make sure your metrics are monoids
• incremental updates
• can handle missing data
Is function composition a monoid?
>>
Function 1
apple -> banana
Function 2
banana -> cherry
New Function
apple -> cherry
Not the same
thing.
Not a monoid 
Is function composition a monoid?
>>
Function 1
apple -> apple
Same thing
Function 2
apple -> apple
Function 3
apple -> apple
A monoid! 
Monads vs. monoids?
=+
Result is same
kind of thing
(Closure)
+
Order not
important
(Associative) Monoid!
+( )
++( )
Monad laws
• Closure, Associativity, Identity
– The monad laws are just the monoid definitions in
diguise
• What happens if you break the monad laws?
– You go to jail
– You lose monoid benefits such as aggregation
A monad is a kind of monoid
"A monad is just a monoid in
the category of endofunctors"
Review
• Partial Application
– For composing functions with multiple parameters
• Bind/Monads
– For composing functions with effects
• Map/Functors
– For composing functions without leaving the other
world
• Monoids
– A general pattern for composing things
Review
• Partial Application
– For composing functions with multiple parameters
• Bind/Monads
– For composing functions with effects
• Map/Functor
– For composing functions without leaving the other
world
• Monoids
– A pattern for composing things
Slides and video here
fsharpforfunandprofit.com/fppatterns
Functional Design Patterns
Thank you!

Contenu connexe

Tendances

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
 
Dr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterDr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterScott Wlaschin
 
Pipeline oriented programming
Pipeline oriented programmingPipeline oriented programming
Pipeline oriented programmingScott 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
 
Enterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeEnterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeScott Wlaschin
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Scott Wlaschin
 
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
 
Why TypeScript?
Why TypeScript?Why TypeScript?
Why TypeScript?FITC
 
Designing with Capabilities
Designing with CapabilitiesDesigning with Capabilities
Designing with CapabilitiesScott Wlaschin
 
Clean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a MonolithClean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a MonolithVictor Rentea
 
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
 
Clean pragmatic architecture @ devflix
Clean pragmatic architecture @ devflixClean pragmatic architecture @ devflix
Clean pragmatic architecture @ devflixVictor Rentea
 
Vertical Slicing Architectures
Vertical Slicing ArchitecturesVertical Slicing Architectures
Vertical Slicing ArchitecturesVictor Rentea
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented ProgrammingScott Wlaschin
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlinintelliyole
 
Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScriptNascenia IT
 
clean code book summary - uncle bob - English version
clean code book summary - uncle bob - English versionclean code book summary - uncle bob - English version
clean code book summary - uncle bob - English versionsaber tabatabaee
 

Tendances (20)

Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)
 
Dr Frankenfunctor and the Monadster
Dr Frankenfunctor and the MonadsterDr Frankenfunctor and the Monadster
Dr Frankenfunctor and the Monadster
 
Pipeline oriented programming
Pipeline oriented programmingPipeline oriented programming
Pipeline oriented programming
 
The Power Of Composition (DotNext 2019)
The Power Of Composition (DotNext 2019)The Power Of Composition (DotNext 2019)
The Power Of Composition (DotNext 2019)
 
Enterprise Tic-Tac-Toe
Enterprise Tic-Tac-ToeEnterprise Tic-Tac-Toe
Enterprise Tic-Tac-Toe
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)
 
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
 
Why TypeScript?
Why TypeScript?Why TypeScript?
Why TypeScript?
 
Designing with Capabilities
Designing with CapabilitiesDesigning with Capabilities
Designing with Capabilities
 
Clean code slide
Clean code slideClean code slide
Clean code slide
 
Clean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a MonolithClean Pragmatic Architecture - Avoiding a Monolith
Clean Pragmatic Architecture - Avoiding a Monolith
 
Domain Modeling Made Functional (KanDDDinsky 2019)
Domain Modeling Made Functional (KanDDDinsky 2019)Domain Modeling Made Functional (KanDDDinsky 2019)
Domain Modeling Made Functional (KanDDDinsky 2019)
 
Clean pragmatic architecture @ devflix
Clean pragmatic architecture @ devflixClean pragmatic architecture @ devflix
Clean pragmatic architecture @ devflix
 
Clean code
Clean codeClean code
Clean code
 
Vertical Slicing Architectures
Vertical Slicing ArchitecturesVertical Slicing Architectures
Vertical Slicing Architectures
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlin
 
JavaScript Inheritance
JavaScript InheritanceJavaScript Inheritance
JavaScript Inheritance
 
Advanced JavaScript
Advanced JavaScriptAdvanced JavaScript
Advanced JavaScript
 
clean code book summary - uncle bob - English version
clean code book summary - uncle bob - English versionclean code book summary - uncle bob - English version
clean code book summary - uncle bob - English version
 

Similaire à Functional Design Patterns (DevTernity 2018)

Why you-dont-need-design-patterns-in-python
Why you-dont-need-design-patterns-in-pythonWhy you-dont-need-design-patterns-in-python
Why you-dont-need-design-patterns-in-pythonSivanagaraju Pachipulusu
 
Extreme Swift
Extreme SwiftExtreme Swift
Extreme SwiftMovel
 
Introduction to C++
Introduction to C++ Introduction to C++
Introduction to C++ Bharat Kalia
 
Cleaner Code - CodeStock 2019 Edition
Cleaner Code - CodeStock 2019 EditionCleaner Code - CodeStock 2019 Edition
Cleaner Code - CodeStock 2019 EditionDave Fancher
 
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
 
DITEC - Programming with C#.NET
DITEC - Programming with C#.NETDITEC - Programming with C#.NET
DITEC - Programming with C#.NETRasan Samarasinghe
 
Twins: Object Oriented Programming and Functional Programming
Twins: Object Oriented Programming and Functional ProgrammingTwins: Object Oriented Programming and Functional Programming
Twins: Object Oriented Programming and Functional ProgrammingRichardWarburton
 
F# as our day job by 2016
F# as our day job by 2016F# as our day job by 2016
F# as our day job by 2016Tomas Jansson
 
Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987乐群 陈
 
elm-d3 @ NYC D3.js Meetup (30 June, 2014)
elm-d3 @ NYC D3.js Meetup (30 June, 2014)elm-d3 @ NYC D3.js Meetup (30 June, 2014)
elm-d3 @ NYC D3.js Meetup (30 June, 2014)Spiros
 
Think sharp, write swift
Think sharp, write swiftThink sharp, write swift
Think sharp, write swiftPascal Batty
 
Functional Programming in C#
Functional Programming in C#Functional Programming in C#
Functional Programming in C#Giorgio Zoppi
 
03 and 04 .Operators, Expressions, working with the console and conditional s...
03 and 04 .Operators, Expressions, working with the console and conditional s...03 and 04 .Operators, Expressions, working with the console and conditional s...
03 and 04 .Operators, Expressions, working with the console and conditional s...Intro C# Book
 
Practical Meta Programming
Practical Meta ProgrammingPractical Meta Programming
Practical Meta ProgrammingReggie Meisler
 
SeneJug java_8_prez_122015
SeneJug java_8_prez_122015SeneJug java_8_prez_122015
SeneJug java_8_prez_122015senejug
 

Similaire à Functional Design Patterns (DevTernity 2018) (20)

Php basics
Php basicsPhp basics
Php basics
 
Why you-dont-need-design-patterns-in-python
Why you-dont-need-design-patterns-in-pythonWhy you-dont-need-design-patterns-in-python
Why you-dont-need-design-patterns-in-python
 
Extreme Swift
Extreme SwiftExtreme Swift
Extreme Swift
 
Introduction to C++
Introduction to C++ Introduction to C++
Introduction to C++
 
Cleaner Code - CodeStock 2019 Edition
Cleaner Code - CodeStock 2019 EditionCleaner Code - CodeStock 2019 Edition
Cleaner Code - CodeStock 2019 Edition
 
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#
 
Welcome to python workshop
Welcome to python workshopWelcome to python workshop
Welcome to python workshop
 
DITEC - Programming with C#.NET
DITEC - Programming with C#.NETDITEC - Programming with C#.NET
DITEC - Programming with C#.NET
 
Twins: Object Oriented Programming and Functional Programming
Twins: Object Oriented Programming and Functional ProgrammingTwins: Object Oriented Programming and Functional Programming
Twins: Object Oriented Programming and Functional Programming
 
F# as our day job by 2016
F# as our day job by 2016F# as our day job by 2016
F# as our day job by 2016
 
Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987Compiler2016 by abcdabcd987
Compiler2016 by abcdabcd987
 
elm-d3 @ NYC D3.js Meetup (30 June, 2014)
elm-d3 @ NYC D3.js Meetup (30 June, 2014)elm-d3 @ NYC D3.js Meetup (30 June, 2014)
elm-d3 @ NYC D3.js Meetup (30 June, 2014)
 
Think sharp, write swift
Think sharp, write swiftThink sharp, write swift
Think sharp, write swift
 
Functional Programming in C#
Functional Programming in C#Functional Programming in C#
Functional Programming in C#
 
03 and 04 .Operators, Expressions, working with the console and conditional s...
03 and 04 .Operators, Expressions, working with the console and conditional s...03 and 04 .Operators, Expressions, working with the console and conditional s...
03 and 04 .Operators, Expressions, working with the console and conditional s...
 
Practical Meta Programming
Practical Meta ProgrammingPractical Meta Programming
Practical Meta Programming
 
Unit 4 (1)
Unit 4 (1)Unit 4 (1)
Unit 4 (1)
 
functions
functionsfunctions
functions
 
SeneJug java_8_prez_122015
SeneJug java_8_prez_122015SeneJug java_8_prez_122015
SeneJug java_8_prez_122015
 
Code optimization
Code optimization Code optimization
Code optimization
 

Plus de 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
 
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
 
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
 
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
 
An introduction to property based testing
An introduction to property based testingAn introduction to property based testing
An introduction to property based testingScott Wlaschin
 

Plus de 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...
 
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)
 
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
 
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
 

Dernier

Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsChristian Birchler
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 

Dernier (20)

Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
Advantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your BusinessAdvantages of Odoo ERP 17 for Your Business
Advantages of Odoo ERP 17 for Your Business
 
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 

Functional Design Patterns (DevTernity 2018)

  • 2. This talk A whirlwind tour of many sights Don't worry if you don't understand everything
  • 3. HOW I GOT HERE
  • 5. I used to be a normal programmer...
  • 6. And then I was introduced to some functional programmers…
  • 8. Now I can say this with a straight face: “A monad is just a monoid in the category of endofunctors, what’s the problem?”
  • 10. • Single Responsibility Principle • Open/Closed principle • Dependency Inversion Principle • Interface Segregation Principle • Factory pattern • Strategy pattern • Decorator pattern • Visitor pattern OO pattern/principle
  • 11. • Single Responsibility Principle • Open/Closed principle • Dependency Inversion Principle • Interface Segregation Principle • Factory pattern • Strategy pattern • Decorator pattern • Visitor pattern OO pattern/principle Borg response
  • 12. • Single Responsibility Principle • Open/Closed principle • Dependency Inversion Principle • Interface Segregation Principle • Factory pattern • Strategy pattern • Decorator pattern • Visitor pattern • Functions • Functions • Functions, also • Functions • You will be assimilated! • Functions again • Functions • Resistance is futile! OO pattern/principle FP equivalent Seriously, FP patterns are different
  • 13. Overview • 3 Core Principles of FP design • Pattern 1: Functions as parameters • Pattern 2: Composing multi-parameter functions • Pattern 3: "bind" • Pattern 4: "map" • Pattern 5: Monoids
  • 14. THREE CORE PRINCIPLES OF FUNCTIONAL PROGRAMMING There are more...
  • 15. Core principles of FP Function Types are not classes Functions are things Composition everywhere
  • 16. Core principle: Functions are things Function
  • 17. The Tunnel of Transformation Function apple -> banana A function is a standalone thing, not attached to a class
  • 18. let z = 1 1 let addOne x = x + 1 int-> int
  • 20. intInt ->int Function as input (int->int)->int
  • 21. int int Function as parameterint->int int->int
  • 23. Function 1 apple -> banana Function 2 banana -> cherry
  • 24. >> Function 1 apple -> banana Function 2 banana -> cherry
  • 25. New Function apple -> cherry Can't tell it was built from smaller functions! Where did the banana go?
  • 26. Composition works at all scales
  • 28. Low-level operation Service AddressValidator For those under 30... Validation Result Address Low-level operation Low-level operation a "service" is just like a microservice but without the "micro" in front
  • 31. Core principle: Types are not classes So, what is a type then?
  • 34. Set of valid inputs Set of valid outputs Function A type is a just a name for a set of things
  • 35. Set of valid inputs Set of valid outputs Function 1 2 3 4 5 6 This is type "integer"
  • 36. Set of valid inputs Set of valid outputs Function This is type "string" "abc" "but" "cobol" "double" "end" "float"
  • 37. 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
  • 38. Set of valid inputs Set of valid outputs Function This is type "Fruit"
  • 39. Set of valid inputs Set of valid outputs Function This is a type of Fruit->Fruit functions
  • 40. Composition everywhere: Types can be composed too "Algebraic type system" "Composable type system"
  • 41.
  • 42. New types are built from smaller types by: Composing with “AND” Composing with “OR”
  • 43. Example: tuples, structs, records FruitSalad = One each of and and “AND” types (Record types) type FruitSalad = { Apple: AppleVariety Banana: BananaVariety Cherry: CherryVariety }
  • 44. Snack = or or “OR” types (Choice types) type Snack = | Apple of AppleVariety | Banana of BananaVariety | Cherry of CherryVariety
  • 45. Real world example of type composition
  • 46. Example of some requirements: We accept three forms of payment: Cash, Check, or Card. For Cash we don't need any extra information For Checks we need a check number For Cards we need a card type and card number
  • 47. interface IPaymentMethod {..} class Cash() : IPaymentMethod {..} class Check(int checkNo): IPaymentMethod {..} class Card(string cardType, string cardNo) : IPaymentMethod {..} In OOP you would probably implement it as an interface and a set of subclasses, like this:
  • 48. type CheckNumber = int type CardNumber = string In FP you would probably implement by composing types, like this:
  • 49. type CheckNumber = ... type CardNumber = … type CardType = Visa | Mastercard type CreditCardInfo = { CardType : CardType CardNumber : CardNumber }
  • 50. type CheckNumber = ... type CardNumber = ... type CardType = ... type CreditCardInfo = ... type PaymentMethod = | Cash | Check of CheckNumber | Card of CreditCardInfo
  • 51. type CheckNumber = ... type CardNumber = ... type CardType = ... type CreditCardInfo = ... type PaymentMethod = | Cash | Check of CheckNumber | Card of CreditCardInfo type PaymentAmount = decimal type Currency = EUR | USD
  • 52. type CheckNumber = ... type CardNumber = ... type CardType = ... type CreditCardInfo = ... type PaymentMethod = | Cash | Check of CheckNumber | Card of CreditCardInfo type PaymentAmount = decimal type Currency = EUR | USD type Payment = { Amount : PaymentAmount Currency: Currency Method: PaymentMethod }
  • 53. type CheckNumber = int type CardNumber = string type CardType = Visa | Mastercard type CreditCardInfo = CardType * CardNumber type PaymentMethod = | Cash | Check of CheckNumber | Card of CreditCardInfo type PaymentAmount = decimal type Currency = EUR | USD type Payment = { Amount : PaymentAmount Currency: Currency Method: PaymentMethod }
  • 54. Design principle: Use static types for domain modelling and documentation Static types only! Sorry Clojure and JS developers 
  • 55. A big topic and not enough time   More on DDD and designing with types at fsharpforfunandprofit.com/ddd
  • 58. let printList() = for i in [1..10] do printfn "the number is %i" i
  • 59. So parameterize the data let printList aList = for i in aList do printfn "the number is %i" i
  • 60. let printList aList = for i in aList do printfn "the number is %i" i
  • 61. let printList anAction aList = for i in aList do anAction i So parameterize the action as well: We've decoupled the behavior from the data. Any list, any action!
  • 63. public static int Product(int n) { int product = 1; for (int i = 1; i <= n; i++) { product *= i; } return product; } public static int Sum(int n) { int sum = 0; for (int i = 1; i <= n; i++) { sum += i; } return sum; }
  • 64. public static int Product(int n) { int product = 1; for (int i = 1; i <= n; i++) { product *= i; } return product; } public static int Sum(int n) { int sum = 0; for (int i = 1; i <= n; i++) { sum += i; } return sum; }
  • 65. public static int Product(int n) { int product = 1; for (int i = 1; i <= n; i++) { product *= i; } return product; } public static int Sum(int n) { int sum = 0; for (int i = 1; i <= n; i++) { sum += i; } return sum; }
  • 67. public static int Aggregate( int initialValue, Func<int,int,int> action, int n) { int totalSoFar = initialValue; for (int i = 1; i <= n; i++) { totalSoFar = action(totalSoFar,i); } return totalSoFar; }
  • 68. Tip: Function types are "interfaces"
  • 69. interface IBunchOfMethods { int DoSomething(int x); string DoSomethingElse(int x); void DoAThirdThing(string x); } Let's take the Single Responsibility Principle and the Interface Segregation Principle to the extreme... Every interface should have only one method!
  • 70. interface IBunchOfMethods { int DoSomething(int x); } An interface with one method is a just a function type type DoSomething: int -> int
  • 71. type DoSomething: int -> int *Any* function with that type is compatible with it let add2 x = x + 2 // int -> int let times3 x = x * 3 // int -> int No interface declaration needed!
  • 73. let isEven x = ... // int -> bool isEvenint bool Log the input Log the output
  • 74. let isEven x = ... // int -> bool isEvenint bool isEvenint boollogint int logbool bool Compose!
  • 75. let isEven x = ... // int -> bool isEvenint bool logint log boolisEven
  • 76. let isEven x = ... // int -> bool isEvenint bool int log bool let isEvenWithLogging = // int -> bool Substitutable for original isEven isEvenWithLogging
  • 77. Tip: "Use interfaces for loose coupling" Use function parameters for loose coupling
  • 79. Bad news: Composition patterns only work for functions that have one parameter! 
  • 80. Good news! Every function can be turned into a one parameter function 
  • 81. let add x y = x + y let add = (fun x y -> x + y) let add x = (fun y -> x + y) int-> int->int int-> int->int int-> (int->int) Normal function (Two parameters)
  • 82. let add x y = x + y let add = (fun x y -> x + y) let add x = (fun y -> x + y) int-> int->int int-> int->int int-> (int->int)
  • 84. let name = "Scott" printfn "Hello, my name is %s" name
  • 85. let name = "Scott" (printfn "Hello, my name is %s") name
  • 86. let hello = (printfn "Hello, my name is %s") Can reuse "hello" in many places now! let name = "Scott" hello name let name = "Alice" hello name
  • 88. let names = ["Alice"; "Bob"; "Scott"] List.iter hello names //foreach name in names let hello = printfn "Hello, my name is %s"
  • 89. let add1 = (+) 1 let equals2 = (=) 2 [1..100] |> List.map add1 |> List.filter equals2
  • 92. let example input = let x = doSomething input if x <> null then let y = doSomethingElse x if y <> null then let z = doAThirdThing y if z <> null then let result = z result else null else null else null I know you could do early returns, but bear with me...
  • 93. 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 -> z // final result ) ) )
  • 94. let example input = let x = doSomething input if x <> null then let y = doSomethingElse x if y <> null then let z = doAThirdThing y if z <> null then let result = z result else null else null else null Nulls are a code smell: replace with Option! Let's fix this!
  • 95. let example input = let x = doSomething input if x.IsSome then let y = doSomethingElse (x.Value) if y.IsSome then let z = doAThirdThing (y.Value) if z.IsSome then let result = z.Value Some result else None else None else None Much more elegant, yes? No! This is fugly! But there is a pattern we can exploit...
  • 96. let example input = let x = doSomething input if x.IsSome then let y = doSomethingElse (x.Value) if y.IsSome then let z = doAThirdThing (y.Value) if z.IsSome then // do something with z.Value // in this block else None else None else None
  • 97. let example input = let x = doSomething input if x.IsSome then let y = doSomethingElse (x.Value) if y.IsSome then // do something with y.Value // in this block else None else None
  • 98. let example input = let x = doSomething input if x.IsSome then // do something with x.Value // in this block else None Can you see the pattern?
  • 99. if opt.IsSome then //do something with opt.Value else None
  • 100. let ifSomeDo f opt = if opt.IsSome then f opt.Value else None
  • 101. let example input = doSomething input |> ifSomeDo doSomethingElse |> ifSomeDo doAThirdThing |> ifSomeDo ... let ifSomeDo f opt = if opt.IsSome then f opt.Value else None
  • 102. Some None Input -> This is an example of a more general problem
  • 104.
  • 105.
  • 106. >> >> Composing one-track functions is fine...
  • 107. >> >> ... and composing two-track functions is fine...
  • 108.   ... but composing switches is not allowed!
  • 109. How to combine the mismatched functions?
  • 110. “Bind” is the answer! Bind all the things!
  • 111. Two-track input Two-track input One-track input Two-track input  
  • 112. Two-track input Slot for switch function Two-track output
  • 114. let bind nextFunction optionInput = match optionInput with | Some s -> nextFunction s | None -> None Two-track input Two-track output
  • 115. let bind nextFunction optionInput = match optionInput with | Some s -> nextFunction s | None -> None Two-track input Two-track output
  • 116. let bind nextFunction optionInput = match optionInput with | Some s -> nextFunction s | None -> None Two-track input Two-track output
  • 117. let bind nextFunction optionInput = match optionInput with | Some s -> nextFunction s | None -> None Two-track input Two-track output
  • 118. Pattern: Use bind to chain options
  • 119. let example input = let x = doSomething input if x.IsSome then let y = doSomethingElse (x.Value) if y.IsSome then let z = doAThirdThing (y.Value) if z.IsSome then let result = z.Value Some result else None else None else None Before
  • 120. let bind f opt = match opt with | Some v -> f v | None -> None After
  • 121. let example input = doSomething input |> bind doSomethingElse |> bind doAThirdThing |> bind ... let bind f opt = match opt with | Some v -> f v | None -> None No pyramids! Code is linear and clear. This pattern is called “monadic bind” After
  • 122. Pattern: Use bind to chain tasks a.k.a "promise" "future"
  • 124. 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 -> z // final result ) ) ) Before
  • 125. let taskBind f task = task.WhenFinished (fun taskResult -> f taskResult) let taskExample input = startTask input |> taskBind startAnotherTask |> taskBind startThirdTask |> taskBind ... This pattern is also a “monadic bind” After
  • 126. Pattern: Use bind to chain error handlers
  • 127. string UpdateCustomerWithErrorHandling() { var request = receiveRequest(); validateRequest(request); canonicalizeEmail(request); db.updateDbFromRequest(request); smtpServer.sendEmail(request.Email) return "OK"; }
  • 128. string UpdateCustomerWithErrorHandling() { var request = receiveRequest(); var isValidated = validateRequest(request); if (!isValidated) { return "Request is not valid" } canonicalizeEmail(request); db.updateDbFromRequest(request); smtpServer.sendEmail(request.Email) return "OK"; }
  • 129. string UpdateCustomerWithErrorHandling() { var request = receiveRequest(); var isValidated = validateRequest(request); if (!isValidated) { return "Request is not valid" } canonicalizeEmail(request); var result = db.updateDbFromRequest(request); if (!result) { return "Customer record not found" } smtpServer.sendEmail(request.Email) return "OK"; }
  • 130. string UpdateCustomerWithErrorHandling() { var request = receiveRequest(); var isValidated = validateRequest(request); if (!isValidated) { return "Request is not valid" } canonicalizeEmail(request); try { var result = db.updateDbFromRequest(request); if (!result) { return "Customer record not found" } } catch { return "DB error: Customer record not updated" } smtpServer.sendEmail(request.Email) return "OK"; }
  • 131. string UpdateCustomerWithErrorHandling() { var request = receiveRequest(); var isValidated = validateRequest(request); if (!isValidated) { return "Request is not valid" } canonicalizeEmail(request); try { var result = db.updateDbFromRequest(request); if (!result) { return "Customer record not found" } } catch { return "DB error: Customer record not updated" } if (!smtpServer.sendEmail(request.Email)) { log.Error "Customer email not sent" } return "OK"; }
  • 132. string UpdateCustomerWithErrorHandling() { var request = receiveRequest(); var isValidated = validateRequest(request); if (!isValidated) { return "Request is not valid" } canonicalizeEmail(request); try { var result = db.updateDbFromRequest(request); if (!result) { return "Customer record not found" } } catch { return "DB error: Customer record not updated" } if (!smtpServer.sendEmail(request.Email)) { log.Error "Customer email not sent" } return "OK"; }
  • 133. Tip: Use a Result type for error handling
  • 134. Request SuccessValidate Failure type Result = | Ok of SuccessValue | Error of ErrorValue Define a choice type
  • 135. Request SuccessValidate Failure let validateInput input = if input.name = "" then Error "Name must not be blank" else if input.email = "" then Error "Email must not be blank" else Ok input // happy path
  • 138. Functional flow without error handling let updateCustomer = receiveRequest() |> validateRequest |> canonicalizeEmail |> updateDbFromRequest |> sendEmail |> returnMessage Before One track
  • 139. let updateCustomerWithErrorHandling = receiveRequest() |> validateRequest |> canonicalizeEmail |> updateDbFromRequest |> sendEmail |> returnMessage Functional flow with error handling After Two track
  • 140. FP terminology • A monad is – A data type – With an associated bind/flatMap function (and some other stuff) – With a sensible implementation (monad laws). • A monadic function is – A switch/points function – bind/flatMap is used to compose them
  • 141. Tip: Monads are a general purpose way of composing functions with complex outputs
  • 143. World of normal values int string bool World of options Option<int> Option<string> Option<bool>
  • 144. World of options World of normal values int string bool Option<int> Option<string> Option<bool> 
  • 145. World of options World of normal values Option<int> Option<string> Option<bool>  int string bool
  • 146. let add42 x = x + 42 add42 1 // 43
  • 147. let add42ToOption opt = if opt.IsSome then let newVal = add42 opt.Value Some newVal else None 
  • 148. World of options World of normal values add42 
  • 149. World of options World of normal values add42
  • 150. World of options World of normal values option -> -> option Option.map
  • 151. let add42 x = x + 42 add42 1 // 43 let add42ToOption = Option.map add42 add42ToOption (Some 1) // Some 43 
  • 152. World of lists World of normal values List.map list-> -> list
  • 153. let add42ToEach = List.map add42 add42ToEach [1;2;3] // [43;44;45]
  • 154. World of async World of normal values async<T> -> -> async<U> Async.map
  • 155. Guideline: Most wrapped generic types have a “map”. Use it!
  • 156. Guideline: If you create your own generic type, create a “map” for it.
  • 157. FP terminology • A functor is – A data type – With an associated "map" function (with a sensible implementation)
  • 160. 1 + 2 = 3 1 + (2 + 3) = (1 + 2) + 3 1 + 0 = 1 0 + 1 = 1
  • 161. 1 + 2 = 3 Some things A way of combining them
  • 162. 2 x 3 = 6 Some things A way of combining them
  • 163. "a" + "b" = "ab" Some things A way of combining them
  • 164. concat([a],[b]) = [a; b] Some things A way of combining them
  • 165. 1 + 2 1 + 2 + 3 1 + 2 + 3 + 4 Is an integer Is an integer A pairwise operation has become an operation that works on lists!
  • 166. 1 + (2 + 3) = (1 + 2) + 3 Order of combining doesn’t matter 1 + 2 + 3 + 4 (1 + 2) + (3 + 4) ((1 + 2) + 3) + 4 All the same
  • 167. 1 - (2 - 3) = (1 - 2) - 3 Order of combining does matter
  • 168. 1 + 0 = 1 0 + 1 = 1 A special kind of thing that when you combine it with something, just gives you back the original something
  • 169. 42 * 1 = 42 1 * 42 = 42 A special kind of thing that when you combine it with something, just gives you back the original something
  • 170. "" + "hello" = "hello" "hello" + "" = "hello" “Zero” for strings
  • 171. • You start with a bunch of things, and some way of combining them two at a time. • Rule 1 (Closure):The result of combining two things is always another one of the things. • Rule 2 (Associativity):When combining more than two things, which pairwise combination you do first doesn't matter. • Rule 3 (Identity element):There is a special thing called "zero" such that when you combine any thing with "zero" you get the original thing back. A monoid!
  • 172. • Rule 1 (Closure):The result of combining two things is always another one of the things. • Benefit: converts pairwise operations into operations that work on lists. 1 + 2 + 3 + 4 [ 1; 2; 3; 4 ] |> List.reduce (+) We'll see this a lot!
  • 173. 1 * 2 * 3 * 4 [ 1; 2; 3; 4 ] |> List.reduce (*) • Rule 1 (Closure):The result of combining two things is always another one of the things. • Benefit: converts pairwise operations into operations that work on lists.
  • 174. "a" + "b" + "c" + "d" [ "a"; "b"; "c"; "d" ] |> List.reduce (+) • Rule 1 (Closure):The result of combining two things is always another one of the things. • Benefit: converts pairwise operations into operations that work on lists.
  • 175. • Rule 2 (Associativity):When combining more than two things, which pairwise combination you do first doesn't matter. • Benefit: Divide and conquer, parallelization, and incremental accumulation.
  • 177. Parallelization: (1 + 2) (3 + 4) 3 + 7
  • 178. • Rule 2 (Associativity):When combining more than two things, which pairwise combination you do first doesn't matter. • Benefit: Divide and conquer, parallelization, and incremental accumulation.
  • 182. • How can I use reduce on an empty list? • In a divide and conquer algorithm, what should I do if one of the "divide" steps has nothing in it? • When using an incremental algorithm, what value should I start with when I have no data?
  • 183. • Rule 3 (Identity element):There is a special thing called "zero" such that when you combine any thing with "zero" you get the original thing back. • Benefit: Initial value for empty or missing data
  • 185. type OrderLine = {Qty:int; Total:float} let orderLines = [ {Qty=2; Total=19.98} {Qty=1; Total= 1.99} {Qty=3; Total= 3.99} ] How to add them up?
  • 186. type OrderLine = {Qty:int; Total:float} let addPair line1 line2 = let newQty = line1.Qty + line2.Qty let newTotal = line1.Total + line2.Total {Qty=newQty; Total=newTotal} orderLines |> List.reduce addPair // {Qty=6; Total= 25.96} Any combination of monoids is also a monoid Write a pairwise combiner Profit!
  • 188. Customer + Customer + Customer Customer Stats + Customer Stats + Customer Stats Reduce Map Not a monoid A monoid Customer Stats (Total)
  • 189. Hadoop make me a sandwich https://twitter.com/daviottenheimer /status/532661754820829185
  • 191. Monoids in the real world Metrics guideline: Use counters rather than rates Alternative metrics guideline: Make sure your metrics are monoids • incremental updates • can handle missing data
  • 192. Is function composition a monoid? >> Function 1 apple -> banana Function 2 banana -> cherry New Function apple -> cherry Not the same thing. Not a monoid 
  • 193. Is function composition a monoid? >> Function 1 apple -> apple Same thing Function 2 apple -> apple Function 3 apple -> apple A monoid! 
  • 195. =+ Result is same kind of thing (Closure)
  • 197. Monad laws • Closure, Associativity, Identity – The monad laws are just the monoid definitions in diguise • What happens if you break the monad laws? – You go to jail – You lose monoid benefits such as aggregation
  • 198. A monad is a kind of monoid
  • 199. "A monad is just a monoid in the category of endofunctors"
  • 200. Review • Partial Application – For composing functions with multiple parameters • Bind/Monads – For composing functions with effects • Map/Functors – For composing functions without leaving the other world • Monoids – A general pattern for composing things
  • 201. Review • Partial Application – For composing functions with multiple parameters • Bind/Monads – For composing functions with effects • Map/Functor – For composing functions without leaving the other world • Monoids – A pattern for composing things
  • 202. Slides and video here fsharpforfunandprofit.com/fppatterns Functional Design Patterns Thank you!