OOP => FP mindshift
The foundation of Functional Programming
Dawid Furman
> Welcome and thanks for all attenders
> Thank for the communities Scala Dusseldorf, Granada Geek, ScalaMAD
> Big conferences in Andalucia - J on the Beach Malaga, Lambda World Cadiz
Behind the language syntax
The way of thinking about
real or
abstract
entities
their relationships
and communications between eachother
???
The Paradigme
> Q: What is the BIG impact for the programming language syntax?
> E: The syntax is not on the main stage
> E: The syntax is a tool for realize our percetions and thinking about the code
> E: This mindset creates our imagination and constraints for the realizaiton.
> E: This mindset create and restrictions and some kind of the border of the World.
The Anonymous function powered by
λ
The λ expression allows us dynamically create:
1. functions 2. the scope (a lexical scope)
0. Milstone => The lambda function
> Being able to use unname functions to create scope on the flay is an essential tool
for doing much more powerful stuff.
> E: Sygnature of the method
> E: Lexical scope (i : Int) => {val y = 5; (a: Int) => i + y + a}
> E: the difference between functions and method
> E: val - value - immutable variable
Methods => Functions
That difference lying behind the paradigm
1 Milstone => methods are NOT functions AND function literals can be assigned to val(ue)
> E: A function can be store in a collection - for example MAP
> E: All we know methods from OOP - encapsulate an bahavior for the object
> E: Having an references to lamba functions is very important characteristic
> E: The difference between functions and method
> E: The operator _
> Q: What about procedure?
Functions => First class functions
A functions that can be: 1. passed as a argument 2. returned as any other data.
> E: val r = List(1,2,3).sortWith(lessThen)
> E: Literal val k : (Int, Int) => Boolean = (x: Int, y: Int) => x < y
> E: Functions that can be passed and return like any other values.
> E: No sides effects - IO etc.
> E: Pure function For the same arguments return alwasy the same values.
Higher order functions
Another fancy and cool name
Technically is a function that takes as a argument other
function/s
Extract the computation - sounds like good old practices Divide & Conquer and DRY.
1 Milstone => Higher and first class function
> E: Functions that can be passed and return like any other values.
> E: Together with first class function allow us extract the computation.
> Q: What is the type of that function: (Int => Int, Int) => Int
> Q: And the other two functions are: Int => Int
> E: (1 to 10) map ((x: Int) => x * 2)
Closures, Partial Application, and Currying together
Enclose a first class functions inside the lambda function.
> E: Show where the function is seeded.
> E: When you capture a value inside a lambda functions, this is referred to as a closure
> E: Invoking the function with fewer parameter returns an function
which is waiting for the rest paramters.
> E: What about def aMethod (f: Int => Int)(x : Int) = f(x)
Partial Application - give a second thought
result = f(x)(y)(z)
<=>
f1 = f(x) =>
f2 = f1(y) =>
f2(z) = result
2. Milstone => Currying make multiple parameter group real!
Currying
in context of Partial Application
3. Milsone => Partial Application is a tool for a functions pipelines/chain
map, filter, fold/l/r - What they have in common?
¿¿¿Anybody???
¡Recursion!
These Higher Order Functions abstracts away common patterns of recursion.
def filter(p: Int => Boolean): List[Int]
def map[B](f: Int => B): scala.collection.TraversableOnce[B]
def fold[A1 >: Int](z: A1)(op: (A1, A1) => A1): A1
> E: See these construct in REPL
> Q: Who like recursion ?
> E: Why recursion is better then iteration - while - foreach
> E: Avoid state chaning, local variables.
Part I => Checkpoint
=> lambda and lexical scope
=> first class functions
=> higher order functions
=> partial application, currying, closures
=> function composition/chain
> E: (a:A) => f(g(a))
> E: (b:B) => f(a,b)
> Q: Why function composition is so important? get rid of all local mutable values
that are potential source of most of the errors.
Part II
Functional domain modeling
Data structures just are. They don`t do anything.
Joe Armstrong, Erlang creator.
Before immutablity...
Programs are just a collection of functions should:
Pure => never ever changing state/s == no side effects
Total => returns values for all inputs
Deterministic => returns the same result for the same input
4. Milstone => Referencial transparency = put all traits together
> Q: What is A(a) - new state
> Q: How we can recognize impure method signature?
> E: We can call this state changing - update it by copy
> E: Define good and bad state
Data modeling OOP vs. FP approach
OOP <=> encapsulate/couples state and behaviour
class Status{
private int code;
private String statusMessage;
}
class Status (var code: Int, var statusMessage: String)
FP <=> decouple them.
case class Status(code: Int, statusMessage: String)
E: ADT :: Product Type, Sum Type, Exponential Type
Data modeling FP approach
ADT - Algebraic Data Types
Where is the bridge between ADT:
1. Math => ¡Cardinality!
2. Immutablity => (Encapsulation by definition,
Isolation by single source of truth,
Immutable state of transfer)
Q: But where it the bridge between ADT and Math!?
E: Defensive copy of object insted of mutable the state
"Good OOP is nothing more then FP in disguise."
"Design patterns are for fill the gap of the OOP abstractions lack."
"With the power paradigm you don`t need any framework for DI."
"In FP it is a common practice to compose and build computation pipelines
and defere evaluation until the end."
"In FP it is easy, and expected, to factor out common
functionality into generic, reusable components that can be composed each other."
But... Where IS the power of FP that we talk about?!
> E: Sorry for that - but there is no single answer for that!
Everything is around Context!
The comprehension of for-comprehension expression
// This signature is only for the List
def flatMap[B](f: Int => List[B]): List[B]
5 Milstone => For-comprehension - a syntactic sugar for combination flatMap(s)/map together in a readable form
> Q: For what Type Classes are? A: Abstracting computations - Operation, Computational Context, Iteration
> Q: Is not it tedious? IT IS!
> E:
val result = for {
a <- aSomeValueA
b <- aSomeValueB
} yield a + b
> E: Discussion about Option, Future
Putting it all together
DI in a functional way
¡doItHereTogether!
The last Milstone:
For-Comprehension
> E: You know Spring, right?
> E: So this is one of the power of FP.
> E: trait Travel
> E: trait Repository[IdType, A]
> E: trait TravelRespository extends Repository[String, Travel]
> E: class TravelRposiotryArangoDB extends TravelRepository
> E: trait TravelService[Travel]{
def createTravelRequest (from: String, to: String) : Option[Travel]
> E: object TravelServiceLiftedImp extends TravelServiceLifted[Travel]
case class Reader[E, A](run: E => A) {
def map[B](f: A => B): Reader[E, B] = Reader(r => f(run(r)))
def flatMap[B](f: A => Reader[E, B]): Reader[E, B] = Reader(r => f(run(r)).run(r))
}
> E: Lifting to Function1[_,_]
Checkpoint Part II
=> OOP Application is a squence of statmens written in imperative way
where each statments is changing the program state.
=> FP is a sequence of exrepssion written in declarative way
where each expression represent a chain of transfromation without any chunks of mutability
that could provoke hidden state change.
More and more about FP
=> Pattern Matching - power of the types
=> Type classes vs. Interfaces
=> Kinds - as a labels for the types
=> GADTs - Generalized ADT
=> A better Scala REPL ammonite.io
Scala -> Haskell
References
¡Málaga Scala Developers!
¡Muchas Gracias!
¿Preguntas?