intro to functional programming

114
Introduction to Functional Programming

Upload: jordan-parmer

Post on 05-Apr-2017

69 views

Category:

Software


1 download

TRANSCRIPT

Page 1: Intro to Functional Programming

Introduction to Functional

Programming

Page 2: Intro to Functional Programming

hello!Jordan Parmer

@ProfParmer

Page 3: Intro to Functional Programming

What is Functional Programming?

Page 4: Intro to Functional Programming

A Very Short Story

Page 5: Intro to Functional Programming

Page 6: Intro to Functional Programming

“We are builders first; technologists second

Page 7: Intro to Functional Programming

“The better builders we are, the more value we provide.

Page 8: Intro to Functional Programming

1.What is Functional

Programming?

Page 9: Intro to Functional Programming

What Does It Mean to be Imperative?

Page 10: Intro to Functional Programming

What Are The Most Common Problems In

Imperative OOP Code?

Page 11: Intro to Functional Programming

Null Pointer ExceptionsConcurrency Errors With Shared State

Broad Context of ReasoningDeep Inheritance Chains

Mutable State

Page 12: Intro to Functional Programming

What is the emphasis with imperative OOP

code?

Page 13: Intro to Functional Programming

Inheritance over composition

Abstraction by Inheritance

Internal class state and encapsulation

Imperative state mutations

Page 14: Intro to Functional Programming

Can We Do Better?

Page 15: Intro to Functional Programming

Return to Roots

Page 16: Intro to Functional Programming

“A functional programming language is a language that

emphasises programming with pure functions and immutable

data

Page 17: Intro to Functional Programming

Functional ProgrammingDeclarativeDescribe what, not howExpressions over statements

IdempotentImmutabilityFunctions are without side-effectsResults deterministic

Referentially TransparentAny expression can be replaced with the results of its value

AlgebraicTypes, equality, expressionsCategory theory

Functionally ComposableSeparate behavior from dataSmall functions composed together to make small building blocks

ParallelizableIdempotent code by nature enables local and distributed parallelization

Page 18: Intro to Functional Programming

Myths✘Requires a math degree to understand

✘Targets only math/science problems

✘Only relevant in academic circles

✘Not for “Line of Business” or “Form Over Data” apps

Page 19: Intro to Functional Programming

LIES!

Page 20: Intro to Functional Programming

Shocking Adjustments✘No Null✘Recursion over looping✘Avoidance of if-statements✘Map/filter/fold over iterating✘Monadic I/O✘Lots of foreign mathematical nomenclature✘No debuggers

Page 21: Intro to Functional Programming

“OOP makes code understandable by encapsulating moving parts.

FP makes code understandable by minimizing moving parts.

✘Michael Feathers

Page 22: Intro to Functional Programming

We Want These

Page 23: Intro to Functional Programming

You Don’t Need a Functional Language To

Be Functional

Page 24: Intro to Functional Programming

But It Does Help

Page 25: Intro to Functional Programming

Some [Subjective] ExamplesPure-ish

✘ Haskell✘ Erlang✘ Elm✘ Hope✘ Joy✘ Mercury✘ Scheme

Hybrids✘ Scala✘ F#✘ Kotlin✘ Swift✘ ML✘ LISP✘ Rust✘ Groovy✘ R✘ Dart✘ Ruby

Progressively Incorporating✘ Java 8✘ C#✘ Python✘ C++ 11

...and many more

Page 26: Intro to Functional Programming

Popular Languages

Beware Bias Ahead

Page 27: Intro to Functional Programming

JVM LanguagesScala

✘ Statically strong typed✘ FP with OOP good parts✘ Higher-order functions ✘ Insanely advanced type system✘ Currying, lazy-evaluation, pattern matching, etc.✘ Large commercial adoption

Twitter, Spotify, LinkedIn, Apache Spark, Kafka, etc.

✘ Backed by Lightbend + Scala Centre

Clojure✘ Dynamically typed✘ First-order functions✘ S-expressions✘ LISP-dialect

“Modern LISP that is symbiotic with Java”

Page 28: Intro to Functional Programming

.NET Languages

F#✘ Statically typed✘ Multi-paradigm: FP, imperative, OOP✘ .NET Framework✘ Visual Studio Tooling✘ Backed by Microsoft

Page 29: Intro to Functional Programming

Apple Languages

Swift✘ Scala...brought to you by Apple

I kid! I kid!

✘ FP alternative to Objective C✘ Borrowed some constructs from C & Objective

C✘ Optional types✘ Categories (i.e. type-classes)

Page 30: Intro to Functional Programming

Erlang Languages

Erlang✘ Ideal for distributed systems✘ Fault-tolerant, real-time✘ Highly-available systems✘ BEAM virtual machine

Elixir✘ Higher abstractions on top of Erlang

Reduces boilerplate✘ Runs on BEAM✘ New language but closely related to Erlang

Page 31: Intro to Functional Programming

Purist Languages

Haskell✘ Purely functional✘ Named after Haskell Curry✘ Strong type system✘ Introduced type-classes✘ Strict immutability

Elm✘ FP for the web✘ Graphical layout without destructive updates✘ Interops with (not compiles to)

JavaScript/CSS/HTML

Page 32: Intro to Functional Programming

...And So Many More

Page 33: Intro to Functional Programming

But What Does That All Mean?

Page 34: Intro to Functional Programming

Let’s Talk About Some FP Concepts

Page 35: Intro to Functional Programming

The SuspectsPure Functions

ExpressionsType Systems

Function ChainingMap, Filter, Fold

Functors, Monoids, Monads

Page 36: Intro to Functional Programming

Side-Effects Are The Source of Many Woes

Page 37: Intro to Functional Programming

Consider Algebra

Page 38: Intro to Functional Programming

f(x) = 3x2-7x+5Given the above

Find f(-4)

Page 39: Intro to Functional Programming

f(x) = 3x2-7x+5Given the above

Find f(-4)81

Page 40: Intro to Functional Programming

Function Has Side-Effects If It...✘Modifies a variable✘Modifies a data structure in place

e.g. append to linked list✘Throws an exception✘Prints to the console✘Writes to a file✘Updates a database✘Draws to the screen

Page 41: Intro to Functional Programming

Function Has Side-Effects If It...✘Modifies a variable✘Modifies a data structure in place

e.g. append to linked list✘Throws an exception✘Prints to the console✘Writes to a file✘Updates a database✘Draws to the screenHave you ever passed a

reference of a list to something else?

Page 42: Intro to Functional Programming

Single InputSingle OutputNo side effectsReferentially transparent Func

A B

Function Is Pure If It...

Page 43: Intro to Functional Programming

Why is this Good?

Page 44: Intro to Functional Programming

Functional Imperative OOP

Pure functions are easy to test

Local reasoning

In => OutVS

Objects are hard to test

Encapsulated state

Context

Global reasoning

Page 45: Intro to Functional Programming

Pure functions are easy to re-use

Low risk

Little-to-no dependencies

VSWe are terrible at making truly reusable objects

Challenges of tight coupling

Hard to abstract at correct level

Functional Imperative OOP

Page 46: Intro to Functional Programming

Pure functions are easy to parallelize

State in isolation

Just lego piecesVS

Sharing is cool in life...not in threads

How many concurrency patterns do we need to deal with shared state?

Functional Imperative OOP

Page 47: Intro to Functional Programming

Pure functions reduce need for most OOP design patterns VS

‘Cause who doesn’t want to know about your MVVMVMVMMVCCC singleton factory observer adapter thingy?

Functional Imperative OOP

Page 48: Intro to Functional Programming

Function Composition

Page 49: Intro to Functional Programming

Single Input Single Output

Func

A B

Page 50: Intro to Functional Programming

Functions Of This Sort Can Be Things

Func

A B

Page 51: Intro to Functional Programming

Functions Of This Sort Can Be Things

Func

A B

Called Functor

Page 52: Intro to Functional Programming

Two Functions

Func

Func

Page 53: Intro to Functional Programming

Compose Them Together

Func

Func

Page 54: Intro to Functional Programming

Compose Them Together

Func

Func

f(g(x))or

F o G x

Page 55: Intro to Functional Programming

New Function!

Func

Page 56: Intro to Functional Programming

Function Composition Is The New Old Injection

Page 57: Intro to Functional Programming

// Goal: Allow brewing coffee with different techniques and beans// Types// Beans => Grind// Grind => Coffee Compose to get: Beans => Coffee

trait Beanstrait Grindtrait Coffee

case class ColumbianBeans() extends Beans

def brew(grind: Beans => Grind)(brew: Grind => Coffee): Beans => Coffee = { brew compose grind}

def burrGrind(beans: Beans): Grind = ???def blendGrind(beans: Beans): Grind = ???

def pourOver(grind: Grind): Coffee = ???def drip(grind: Grind): Coffee = ???def frenchPress(grind: Grind): Coffee = ???

val pourOverWithBurrGrind = brew(burrGrind)(pourOver)val myFavoriteBeans = ColumbianBeans()val myFavoriteCoffee = pourOverWithBurrGrind(myFavoriteBeans)

// TIME TO WAKE UP!!!

Page 58: Intro to Functional Programming

// Goal: Allow brewing coffee with different techniques and beans// Types// Beans => Grind// Grind => Coffee Compose to get: Beans => Coffee

trait Beanstrait Grindtrait Coffee

case class ColumbianBeans() extends Beans

def brew(grind: Beans => Grind)(brew: Grind => Coffee): Beans => Coffee = { brew compose grind}

def burrGrind(beans: Beans): Grind = ???def blendGrind(beans: Beans): Grind = ???

def pourOver(grind: Grind): Coffee = ???def drip(grind: Grind): Coffee = ???def frenchPress(grind: Grind): Coffee = ???

val pourOverWithBurrGrind = brew(burrGrind)(pourOver)val myFavoriteBeans = ColumbianBeans()val myFavoriteCoffee = pourOverWithBurrGrind(myFavoriteBeans)

// TIME TO WAKE UP!!!

brew is a higher order function

Page 59: Intro to Functional Programming

Why Useful?

Page 60: Intro to Functional Programming

// Imagine how many combinations we can use this code// Imagine how easy testing is

object Person { def drink(coffee: Coffee): AwakePerson = ???}

def wakeSomeone(makeIt: () => Coffee): AwakePerson = { Person.drink(makeIt())}

Anything that makes coffee

Page 61: Intro to Functional Programming

Expressions

Page 62: Intro to Functional Programming

// Which right triangle that has integers for all sides and all sides equal to// or smaller than 10 has a perimeter of 24?

def rightTriangle: Seq[Int] = for { c <- 1 to 10 b <- 1 to c a <- 1 to b if ((Math.pow(a,2) + Math.pow(b,2) == Math.pow(c,2)) && (a + b + c == 24)) } yield (a, b, c)

rightTriangle

Answer: [6, 8, 10] It’s Not About the How but the What

Page 63: Intro to Functional Programming

Type Constraints

Page 64: Intro to Functional Programming

f(x) = 3/xInt => Double

Page 65: Intro to Functional Programming

f(x) = 3/x1 => 3/1 => 3.02 => 3/2 => 1.50 => 3/0 => ???

Page 66: Intro to Functional Programming

f(x) = 3/x1 => 3/1 => 3.02 => 3/2 => 1.50 => 3/0 => ???

AH, PICKLES!

Page 67: Intro to Functional Programming

f(x) = 3/x1 => 3/1 => 3.02 => 3/2 => 1.50 => 3/0 => ???

THROW AN EXCEPTION?

Page 68: Intro to Functional Programming

f(x) = 3/xInt => Double

0 => 3/0 => ???

THROW AN EXCEPTION?

THEN THIS IS A LIE!

Page 69: Intro to Functional Programming

f(x) = 3/xInt => Double

0 => 3/0 => ???

THROW AN EXCEPTION?

THEN THIS IS A LIE!

Are You A Liar?

Page 70: Intro to Functional Programming

But Functions Are Types!

Types Don’t Have to Be Open to All

Circumstances

Page 71: Intro to Functional Programming

f(x) = 3/xNonZeroInt => Double

Just Became Constrained And Self-Documented

Page 72: Intro to Functional Programming

f(x) = 3/x Zero Not Allowed BY NonZeroInt

-1 => 3/-1 => -31 => 3/1 => 3

2 => 3/2 => 1.5

Page 73: Intro to Functional Programming

Static Types Just Became Enforced

Domain Documentation

Page 74: Intro to Functional Programming
Page 75: Intro to Functional Programming

We Sometimes Refer to Our Programs as an

“Algebra”

Page 76: Intro to Functional Programming

If It Compiles, It Probably Works

Page 77: Intro to Functional Programming

Function Chaining

Page 78: Intro to Functional Programming

def foo(): Thing = { val x = DoAThing() if (x != null) { val y = DoAnotherThing(x) if (y != null) { val z = DoYetAnotherThing(y) if (z != null) { return z } else { return null } } else { return null } } else { return null }}

Page 79: Intro to Functional Programming

def foo(): Thing = { val x = DoAThing() if (x != null) { val y = DoAnotherThing(x) if (y != null) { val z = DoYetAnotherThing(y) if (z != null) { return z } else { return null } } else { return null } } else { return null }}

Yeah, I know this is bad.

But you know you’ve

seen this before.

Hang with me.

Page 80: Intro to Functional Programming

def foo(): Thing = { val x = DoAThing() if (x != null) { val y = DoAnotherThing(x) if (y != null) { val z = DoYetAnotherThing(y) if (z != null) { return z } else { return null } } else { return null } } else { return null }}

Pyramid of Doom

Page 81: Intro to Functional Programming

def foo(): Thing = { val x = DoAThing() if (x != null) { val y = DoAnotherThing(x) if (y != null) { val z = DoYetAnotherThing(y) if (z != null) { return z } else { return null } } else { return null } } else { return null }}

Pyramid of Doom

The Only Lines Doing

Work

That’s only 20%!

Page 82: Intro to Functional Programming

def foo(): Thing = { val x = DoAThing() if (x != null) { val y = DoAnotherThing(x) if (y != null) { val z = DoYetAnotherThing(y) if (z != null) { return z } else { return null } } else { return null } } else { return null }}

Pyramid of Doom

Look at all those nulls!

Half this code is null checking.

Nulls are a serious code

smell!

Page 83: Intro to Functional Programming

def foo(): Thing = { val x = DoAThing() if (x != null) { val y = DoAnotherThing(x) if (y != null) { val z = DoYetAnotherThing(y) if (z != null) { return z } else { return null } } else { return null } } else { return null }}

Pyramid of Doom

Look at all those nulls!

Half this code is null checking.

Nulls are a serious code

smell!

Null Pointer Exceptions Waiting to Happen

Page 84: Intro to Functional Programming

def foo(): Thing = { val x = DoAThing() if (x != null) { val y = DoAnotherThing(x) if (y != null) { val z = DoYetAnotherThing(y) if (z != null) { return z } else { return null } } else { return null } } else { return null }}

Pyramid of Doom

Throw in async operations, we can

create the same pyramid with

nested callbacks.

Page 85: Intro to Functional Programming

FP to the Rescue!

Page 86: Intro to Functional Programming

def foo(): Option[Int] = { for { x <- DoAThing() y <- DoAnotherThing(x) z <- DoYetAnotherThing(y) } yield z}

Page 87: Intro to Functional Programming

def foo(): Option[Int] = { for { x <- DoAThing() y <- DoAnotherThing(x) z <- DoYetAnotherThing(y) } yield z}

Every line is significant

Page 88: Intro to Functional Programming

def foo(): Option[Int] = { for { x <- DoAThing() y <- DoAnotherThing(x) z <- DoYetAnotherThing(y) } yield z} Boom!

Every line is significant

Page 89: Intro to Functional Programming

Code Examples

Page 90: Intro to Functional Programming

Application Becomes a Collection of Pure

Functions

Page 91: Intro to Functional Programming

Just Fold the Collection

Page 92: Intro to Functional Programming

ParallelizationFold All the Pieces!

Page 93: Intro to Functional Programming
Page 94: Intro to Functional Programming

MonadsThe Key to a Lot of Awesome

And confusion

Page 95: Intro to Functional Programming

Functors, Monoids, and Bears

Page 96: Intro to Functional Programming

Functor

A => B

Page 97: Intro to Functional Programming

Monoid

Type AIdentity Function

Binary Combinator

Page 98: Intro to Functional Programming

Monad

Type with a Functor + FlatMap

Page 99: Intro to Functional Programming

State

Page 100: Intro to Functional Programming

State

State stays in box

Page 101: Intro to Functional Programming

State

The box is a “monad”

Page 102: Intro to Functional Programming

State

Think of monad as

collection of at most one

item

Page 103: Intro to Functional Programming

State

You can do collection things to monadsOperation creates new monad of same type but new state .map(...)

.flatMap(...)

.fold(...)

.filter(...)

.collect(...)

.head

Page 104: Intro to Functional Programming

State

If Monad is “empty”, applied functions are ignored

.map(...)

.flatMap(...)

.fold(...)

.filter(...)

.collect(...)

.head

Page 105: Intro to Functional Programming

def foo(): Option[Int] = Some(100)

val myFoo = foo()

val result = myFoo .map(i => i + 100) .map(i => i.toString) .map(i => i + " is a bigger number") .getOrElse("didn't do anything")

// result = "200 is a bigger number"

Page 106: Intro to Functional Programming

def foo(): Option[Int] = None

val myFoo = foo()

val result = myFoo .map(i => i + 100) .map(i => i.toString) .map(i => i + " is a bigger number") .getOrElse("didn't do anything")

// result = "didn’t do anything"

Executed but not applied

Page 107: Intro to Functional Programming

Monads are so much more but let’s keep it

simple for now…

...another talk to come

Page 108: Intro to Functional Programming

2.

Common Applications

Page 109: Intro to Functional Programming

Trends in Functional Programming

Data Processing Streaming Parallelizatio

n

Machine Learning

Heavy Computation Attracting

Talent

Page 110: Intro to Functional Programming

3.

Disadvantages?

Page 111: Intro to Functional Programming
Page 112: Intro to Functional Programming

4.

Final Thoughts

Page 113: Intro to Functional Programming

Natural way to migrate To Functional

Programming?

Page 114: Intro to Functional Programming

thanks!Any questions?

You can find me at@ProfParmer