CHURCH ENCODING
Booleans, integers, (and other data
structures) can be entirely replaced by
lambda calculus!
https://en.wikipedia.org/wiki/Church_encoding
Slide 4
Slide 4 text
zero
one
two
true
false
λf . λx. x
λf . λx. f (x)
λf . λx. f (f (x)
⋮
λx. λy. x
λx. λy. y
Slide 5
Slide 5 text
CHURCH THESIS
Anything that is effectively computable
can be computed by -Calculus
λ
https://en.wikipedia.org/wiki/Church%E2%80%93Turing_thesis
Slide 6
Slide 6 text
Can Programming Be Liberated from the von
Neumann Style? A Functional Style and Its
Algebra of Programs
John Backus
IBM Research Laboratory, San Jose
Turing award 1977
https://news.ycombinator.com/item?id=7671379
Slide 7
Slide 7 text
FUNCTIONAL PROGRAMMING
using mathematical functions
to perform calculations
https://en.wikipedia.org/wiki/Functional_programming
Slide 8
Slide 8 text
FUNCTION
is a relation
between a set of input values
and a set of output values
Slide 9
Slide 9 text
SQUARE
1 ⟶ 1
2 ⟶ 4
3 ⟶ 9
f (x) = x
2
Slide 10
Slide 10 text
Functions are definitions
f (x) =
{
x
2
2x + 1
if x is even
otherwise
Slide 11
Slide 11 text
FP CONCEPTS
Functions as first class citizens
Higher order functions
Pure functions
Lists and recursion
Lazy evaluation
Monads
Slide 12
Slide 12 text
FUNCTIONS AS FIRST CLASS CITIZENS
Slide 13
Slide 13 text
FP is programming with values,
and functions are values
Slide 14
Slide 14 text
VALUES
They can be created by the running program
They can be assigned to variables
They can be passed into functions
They can be returned by functions
Slide 15
Slide 15 text
In Ruby, everything is an object.
Slide 16
Slide 16 text
FUNCTIONS IN RUBY
Regular methods
Callable objects
Slide 17
Slide 17 text
CALLABLE OBJECTS
Proc
lambda
block
Method
Slide 18
Slide 18 text
PROC
add = Proc.new { |x, y| x + y }
# Kernel#proc
add = proc { |x, y| x + y }
# Kernel#lambda
add = lambda { |x, y| x + y }
# => #Proc:0x0000010299a1d0 (lambda)
# stabby lambda
add = -> x, y { x + y }
Slide 19
Slide 19 text
BLOCK
anonymous function
def capture_block(&block)
# a new proc is created
block.call
end
capture_block { puts "Inside the block" }
Slide 20
Slide 20 text
METHOD AS OBJECT
class Cat
def talk
puts "self is #{self}"
end
end
c = Cat.new
# => #Cat:0x00007faf60008888
m = c.method(:talk)
# => #Method: Cat#talk
m.call
# => self is #Cat:0x00007faf60008888
http://ruby-doc.org/core/Object.html#method-i-method
Slide 21
Slide 21 text
CALLING CALLABLE OBJECTS
add = -> x, y { x + y }
add.call(1, 2) # => 3
add.(1, 2) # => 3
add[1, 2] # => 3
Symbol#to_proc
class Symbol
def to_proc
# naive implementation
-> obj { obj.send(self) }
end
end
http://ruby-doc.org/core/Symbol.html#method-i-to_proc
Slide 24
Slide 24 text
Generalizing #to_proc
class Person < Struct.new(:name)
def self.to_proc
-> person { person.name }
end
end
[Person.new("Jack"),
Person.new("Rick")].map &Person
# => ["Jack", "Rick"]
Slide 25
Slide 25 text
FUNCTION OBJECT
class ColorFilter < Struct.new(:color)
def to_proc
-> item { item.color == self.color }
end
def call(list)
list.select &self
end
end
red_filter = ColorFilter.new(:red)
red_filter.call(color_list) ==
color_list.select(&red_filter)
Slide 26
Slide 26 text
FP CONCEPTS
Functions as first class citizens
Higher order functions
Pure functions
Lists and recursion
Lazy evaluation
Monads
Slide 27
Slide 27 text
HIGHER-ORDER FUNCTION
takes one or more functions as arguments
or returns a function as its result
https://en.wikipedia.org/wiki/Higher-order_function
Slide 28
Slide 28 text
FILTER
filter = -> f, list {
list.select &f
}
even = -> x { x % 2 == 0 }
filter.(even, (1..10))
# => [2, 4, 6, 8, 10]
Slide 29
Slide 29 text
MAP
map = -> f, list {
list.map &f
}
double = -> x { x * 2 }
map.(double, (1..5))
# => [2, 4, 6, 8, 10]
Slide 30
Slide 30 text
FOLD
fold = -> f, init, list {
list.reduce(init) { |a, b| f.(a, b) }
}
plus = -> x, y { x + y }
fold.(plus, 0, (1..5)) # => 15
FUNCTION COMPOSITION
f (x) = x + 1
g(x) = x
2
f (g(2)) = 5
g(f (2)) = 9
f ∘ g(x) = + 1
x
2
g ∘ f (x) = (x + 1)
2
Slide 33
Slide 33 text
COMPOSE OPERATOR
class Proc
def ◦(other)
-> (*args) { self.(other.(*args)) }
end
end
even = -> x { x % 2 == 0 }
square = -> x { x * x }
add1 = -> x { x + 1 }
# is (x + 1)^2 even?
f = even.◦ square.◦ add1
f[1] # => true
f[2] # => false
class Counter
attr_reader :count
def initialize(count: 0)
@count = count
end
def inc
@count += 1
self
end
end
Slide 40
Slide 40 text
Are objects and closures equivalent?
http://wiki.c2.com/?ClosuresAndObjectsAreEquivalent
Slide 41
Slide 41 text
FP CONCEPTS
Functions as first class citizens
Higher order functions
Pure functions
Lists and recursion
Lazy evaluation
Monads
Slide 42
Slide 42 text
PURE FUNCTION
Data in, data out
No side effects
parameters → f unction → result
https://en.wikipedia.org/wiki/Pure_function
Slide 43
Slide 43 text
These functions aren't pure:
def f(x)
global_a = global_a + x
end
def h(x)
print x + 1
end
def g(x)
x + read_y
end
Slide 44
Slide 44 text
PURE FUNCTIONS
Referential Transparency
Immutability
Slide 45
Slide 45 text
REFERENTIAL TRANSPARENCY
A expression can be replaced with its corresponding
value without changing the program's behavior.
https://en.wikipedia.org/wiki/Referential_transparency
Referentially opaque
print next_random() + next_random()
# => 1 + 6 = 7
x = next_random() # => 2
print x + x # => 2 + 2 = 4
Slide 48
Slide 48 text
IMMUTABILITY
A name is immutable if the name's value can't change.
a = 3
double_a = 2 * a
https://en.wikipedia.org/wiki/Immutable_object
Slide 49
Slide 49 text
# Not OK
x = x + 1
total = 0
orders.each { |order|
# Not OK
total = total + order.amount
}
print total
Slide 50
Slide 50 text
IMMUTABLE OBJECT
state cannot be modified a er it is created
class Counter
attr_reader :count
def initialize(count: 0)
@count = count
end
def inc
self.class.new(count: count + 1)
end
end
Slide 51
Slide 51 text
BENEFITS OF PURE FUNCTIONS
Can be reused without regard to context
Easier to test and debug, reduce setup
Avoid race condition and achieve thread safety
Memoization
Slide 52
Slide 52 text
No Memoization
fib = -> n {
if n == 0 || n == 1
n
else
fib.(n-1) + fib.(n-2)
end
}
(1..10).map &fib
# => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
Slide 53
Slide 53 text
Controlled Memoization
fib = -> (n, memo = {}) {
if n == 0 || n == 1
n
else
memo[n] ||= fib.(n-1) + fib.(n-2)
end
}
(1..10).map &fib
# => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
Imperative Shell, Functional Core
Boundaries, by Gary Bernhardt, RubyConf 2012
Slide 56
Slide 56 text
FP CONCEPTS
Functions as first class citizens
Higher order functions
Pure functions
Lists and recursion
Lazy evaluation
Monads
Slide 57
Slide 57 text
LISTS AND RECURSION
Slide 58
Slide 58 text
LIST
Sequence of elements of the same type
Possibly empty []
Possibly finite [5,13,7]
Possibly infinite [0,2,4,6,8,10,12,...]
https://en.wikipedia.org/wiki/List_(abstract_data_type)
Slide 59
Slide 59 text
BASIC LIST OPERATIONS
head : list -> value
head([1,2,3]) = 1
tail : list -> list
tail([1,2,3]) = [2,3]
construct : value, list -> list
construct(1, [2,3]) = [1,2,3]
concatenate : list, list -> list
concatenate([1,2], [8,10]) = [1,2,8,10]
Slide 60
Slide 60 text
CONSTRUCT
construct : value, list -> list
3::[5,4,2,1] = [3,5,4,2,1]
8::[] = [8]
h::t = [5,7,9,10]
h = 5
t = [7,9,10]
Slide 61
Slide 61 text
RECURSION
length : list -> number
length([]) = 0
length(h::t) = 1 + length(t)
Slide 62
Slide 62 text
RECURSION
findAt : list, number -> value
findAt(h::t, 1) = h
findAt(h::t, n) = findAt(t, n-1)
Slide 63
Slide 63 text
RECURSION
reverse : list -> list
reverse([]) = []
reverse(h::t) = concat(reverse(t), h)
Slide 64
Slide 64 text
Quciksort: functional style
quicksort([]) = []
quicksort(h::t) = concatenate (
quicksort(filter(( x -> x < h), t)),
[h],
quicksort(filter(( x -> x >= h), t))
)
Slide 65
Slide 65 text
FP CONCEPTS
Functions as first class citizens
Higher order functions
Pure functions
Lists and recursion
Lazy evaluation
Monads
Slide 66
Slide 66 text
LAZY EVALUATION
or call-by-need, is an evaluation strategy which delays
the evaluation of an expression until its value is
needed (non-strict evaluation) and which also avoids
repeated evaluations
https://en.wikipedia.org/wiki/Lazy_evaluation
Slide 67
Slide 67 text
Eager (Strict) evaluation in Ruby
# Infinite list
(1..Float::INFINITY)
.map { |i| i * i }
.first(10)
# never gonna end
Use wrap function to achieve lazy evaluation
wrapped_value = -> {
slow_expression
}
# call-by-need
wrapped_value.()
Slide 70
Slide 70 text
Lazy evaluation in Haskell
take 10 [1..]
# => [1,2,3,4,5,6,7,8,9,10]
take 10
[ x+2 | x <- [ x*x | x <- [1..]]]
# => [3,6,11,18,27,38,51,66,83,102]
https://wiki.haskell.org/Lazy_evaluation
Slide 71
Slide 71 text
Lazy producer-consumer
Slide 72
Slide 72 text
I LIKE LAZINESS
Slide 73
Slide 73 text
FP CONCEPTS
Functions as first class citizens
Higher order functions
Pure functions
Lists and recursion
Lazy evaluation
Monads
Slide 74
Slide 74 text
MONADS
Slide 75
Slide 75 text
f (x) = − 8
1
− 4
x + 6
‾ ‾
‾‾‾
√
error = nil
if x >= -6
y = sqrt(x + 6) - 4
if y == 0
error = true
else
z = 1 / y - 8
end
else
error = true
end
Slide 76
Slide 76 text
MAYBE MONAD
Define a new Maybe a float type
Just a float value
or
Nothing
Slide 77
Slide 77 text
MAYBE MONAD
sqrtMaybe : float -> Maybe a float
sqrtMaybe(x) = if x >= 0
Just sqrt(x)
else
Nothing
Slide 78
Slide 78 text
MAYBE MONAD
reciprocalMaybe : float -> Maybe a float
reciprocalMaybe(x) = if x != 0
Just 1 / x
else
Nothing
Slide 79
Slide 79 text
FUNCTION COMPOSITION
If you have Just y, apply f to y,
getting Just f(y) or Nothing,
if you have Nothing, get Nothing
bind : Maybe a float, f -> Maybe a float
Slide 80
Slide 80 text
bind ( Just 4, sqrtMaybe )
# => Just 2
bind ( Just -1, sqrtMaybe )
# => Nothing
bind ( Nothing, sqrtMaybe )
# => Nothing
DATA PIPELINE
sqrtMaybe(x+6)
⊳ minus4Maybe
⊳ reciprocalMaybe
⊳ minus8Maybe
Slide 83
Slide 83 text
MONAD
1. Define a data type, and rules of values
2. Create functions use the data type
3. Compose functions into actions with rules in #1
https://en.wikipedia.org/wiki/Monad_(functional_programming)
Slide 84
Slide 84 text
Refactoring Ruby with Monads
Tom Stuart, 2014
https://codon.com/refactoring-ruby-with-monads
Slide 85
Slide 85 text
FP CONCEPTS
Functions as first class citizens
Higher order functions
Pure functions
Lists and recursion
Lazy evaluation
Monads
Slide 86
Slide 86 text
FUNCTIONAL MINDSET
Data pipelines
Composition
Pure functions first
Seperate side effects
Immutable value objects
Callable function objects
Functional Abstractions