functional programming - worth the effort
DESCRIPTION
This presentation explores the benefits of functional programming, especially with respect to reliability. It presents a sample of types that allow many program invariants to be enforced by compilers. We also discuss the industrial adoption of functional programming, and conclude with a live coding demo in Scala.TRANSCRIPT
Why Func)onal Programming is Worth the Effort
Contents
• Benefits of func)onal programming • Focus on reliability • Examples: Using the right types • Func)onal Programming in Industry • Live Coding in Scala
Audience Polls
I am most experienced in: ● Java ● C/C++/Obj-‐C/C# ● PHP ● VB ● Python ● JavaScript ● Ruby ● Perl ● Racket ● Other
Audience Polls
My programs work perfectly the first )me I run them:
1. Nearly every )me 2. Frequently 3. Some)mes 4. Rarely 5. Almost Never
What is Func)onal Programming?
● Computa)on as evalua)on of func)ons o No side-‐effects (pure func)ons)
Consequences of Purity
● FP requires higher order func)ons ● Order of evalua)on has no impact on
returned value (as in mathema)cs)
Evalua)on Order: Illustra)on
Given the func)on square(x) = x*x
square(max(3, 4)) max(3, 4) * max(3, 4)
square (4) 4 * 4
Benefits
● Clarity o Referen)al transparency facilitates reasoning
● Conciseness o HOFs enable abstrac)on and favor reuse
● Safety o Effects are values and can be type checked!
● Maintainability o As a consequence
More Benefits
● Concurrency Determinis)c Parallelism:
Order of evalua)on is irrelevant, so parallel evalua)on is fine too.
Type Checking
Type: Essen)ally, a set of admissible values for a variable, a parameter, a field or a return value.
When designing a program we make decisions about types. We should tell the compiler!
Type inference means you don’t have to repeat types constantly to the compiler. It reasons about types, it doesn’t just check them.
You can do pair programming with the compiler.
What about Dynamic Type Checking
Almost no type checking; only primi)ve func)ons are checked.
Adding run)me checks in user func)ons is possible but is slow and is more trouble than sta)c checking. Failed checks require )me-‐consuming diagnosis with debuggers.
Classes of Bugs Es)mates for illustra)on purposes. No real data behind this.
Extreme Reliability
When you play by the rules of type system you avoid almost all errors.
Once it compiles, it works!
Curry-‐Howard Correspondence
Equivalence between ● Proofs (in some logic) ● Programs (in some typed FP language)
Dependently Typed Languages
● Agda ● Idris
Types vs Tests
Tests check a few execu)ons Types check all poten)al execu)ons!
Test Driven to Type Driven Development
Test Driven Development has benefits but also important costs. With the safety brought by types, many tests are no longer required.
Tests can become stale. Some automated tests are s)ll useful.
Documenta)on is Brihle
Change is omnipresent and documenta)on will frequently become stale.
More precise types can act as documenta)on that cannot be out of date.
So you might need a bit less documenta)on.
My Exposure to Func)onal Programming
In 1992: Miranda Was told not to expect to write real sojware with that, more of a toy language.
Func)onal Programming is no longer a toy.
Func)onal Programming in Industry
● Not yet mainstream, but seeing more adop)on
● Many ecosystems sufficiently mature
Func)onal Programming Languages in Industry
● Dynamically Typed o Scheme, Racket, Common Lisp, Clojure, Erlang
● Typed o Haskell o F# o Scala o OCaml
Func)onal Programming at BoldRadius
● Scala is our main JVM language ● .NET developers looking seriously at F#
Using the Right Types
The right type is ● not too strict (strong formula) ● not too loose (weak formula)
Too Strict
Producer works too hard to produce informa)on the consumer does not need.
● Extraneous fields (conjunc)ons, “and”) ● Not enough alterna)ves (disjuc)ons, “or”)
Too Loose
Consumer is missing informa)on that the Producer could easily have provided.
● Missing fields (conjunc)ons, “and”) ● Too many alterna)ves (disjuc)ons, “or”)
Avoid Trying to Future Proof
Building a type for the future ojen makes it too strong or too weak for the current producers and consumers.
Extreme examples: ● “Stringly typed” code encodes everything in strings. ● Using Object in Java
Type Change
As needs change, both types and func)ons should change.
Compiler errors will indicate inconsistencies during refactoring.
Persisted data increases fric)on however.
Examples
Op)onal Values
Dis)nguish what is op)onal and required. Null references should be banned because they can be assigned to all types, making everything op)onal.
data Maybe a = Nothing | Just a data Car = Car Engine Wheels (Maybe AC) Car consumers can rely on the presence of an Engine.
Non Applicable Field
data Account = Account {open :: Boolean, balance :: Dollars}
Too loose: ● We want to disallow a closed account with a non-‐zero balance
data Account2 = Open {balance :: Dollars} | Closed
Duplicate Data
data AgeInfo = AgeInfo {age: Int, minor: Boolean}
Too loose: ● Consumers may rely on these two fields having consistent values.
data AgeInfo2 = AgeInfo2 {age: Int} isMinor :: AgeInfo2 -> Boolean
List with a Selected Element
data Selected1 a = Selected1 (List a) Int Too loose: ● Int index could be out of range ● List could be empty Consumer may get input it does know how to handle.
data Selected2 a = Selected2 (List a) a (List a)
Binary Tree
data Node i a = Node i a a data Tree i a = Leaf a | Internal (Node i (Tree i a)) What if we needed to represent a full binary tree? ● Could use Tree and maintain the “fullness” invariant at run)me. Error prone.
● Or use the right type that checks this at compile )me...
Full Binary Tree (non-‐regular type!)
data Node i a = Node i a a data Full i a = Last a | Level (Full i (Node i a)) a | Node i a | Node i (Node i a) | ... a | (i, a, a) | (i, (i, a, a), (i, a, a)) | ...
Free Monad
data Free f a = Pure a | Roll (f (Free f a)) Equivalent to this: a | f (a | f ( a | … )) Not this: a | f a | f (f a) | ... data Node i a = Node i a a Free (Node i) a is equivalent to Tree i a, not Full i a
More Free Monads
data Command a = WriteLine String a | ReadLine (String -> a) Free Command a = a | Command (a | Command (a | Command (...))) Represents computa)ons doing specific IO opera)ons in a type-‐safe
manner!
Patrick Prémont Func)onal Programming Architect
BoldRadius Solu)ons @ppremont
www.boldradius.com