Here's an introduction to folks using FP in various programming languages (especially those with built-in support for first class functions).
Join Lex Shehan as he shares his journey into FP as a retrospective; it should be great introduction to folks to using FP in other languages (especially those with built-in support for first class functions).
Our journey will include:
* high order functions in javascript (lodash)
* functional programming in Ruby
* going deeper in FP with Scala
* learning Haskell to gain a broader understanding of FP
* the history of FP and what Category Theory has to do with FP
* challenges & opportunities of incorporating FP techniques in Go
16. Map each with index
class Event < MonitorInfo
def self.json
all.each_with_index.map do |m, index|
{ :id => index,
:user => 'sensor',
:date => Time.now,
:policy => I18n.translate(m[:policyname])}
end
end
end
Grab each index
value and assign
‘em to :id
17. Chain high order functions!
def load_dest_addresses(addr)
return if addr.blank?
destination_addresses = DestinationAddressNode.new
destination_addresses.network_object = addr.split(',').reject{|a| a.nil? }.map do |aid|
leaf = RuleLeafNode.ne
leaf.uuid = aid
leaf
end
destination_addresses
end
Awesome!
Too
complicated!
24. When I see patterns in my programs, I consider it a sign of
trouble.
The shape of a program should reflect only the problem it
needs to solve.
Design pattern sub-language
It appears to me that stronger
languages can more easily remove
such duplication because
sometimes one has to make a kind
of sub-language to do it.
- Paul Graham
44. A big complex programming language.
Imperative, Object oriented,
Concurrent, functional
Gateway to large scale frameworks
Machine Learning, data streaming: spark, FLINK, Kafka...
Scala
45. First exposure to scala
class SearchEntityPriceResponse(
entitySearch: EntitySearch,
entitys: List[EntityInfo],
xmlLogHandler: XmlLogHandler) extends (Elem => Seq[EntityResult]) {
private val entitysByGtaCode = entitys.map(h => ((h.gtaCityCode.get + h.gtaPropertyCode.get).hashCode, h)).toMap
class … extends
looks like Java
Seq, map, toMap …
that’s something
different!
46. fp high order functions?
def apply(responseXml: Elem): Seq[EntityResult] = {
xmlLogHandler.logXml(responseXml)
val resultList = (responseXml "Entity") map {
entityEl => {
}
val filteredResultList = resultList.flatten.groupBy(_.entity.id).map(g
=> merge(g._2)).toSeq
filteredResultList
}
entityEl => {
val rateResultList = createEntityRateResult(entityEl)
if (!rateResultList.isEmpty) {
val entityKey = ((entityEl "Location" "@Code").text
+ (entityEl "Item" "@Code").text).hashCode
val entityResult: EntityResult = new EntityResult()
// ...
rateResultList.foreach(_.result = entityResult)
Some(entityResult)
} else {
None
}
}
}
47. Scala’s functional
programming stuff
Currying
Tail Recursion
Higher Order Functions
Anonymous Functions
Lambda Functions
Partial Functions
Everything is an
Expression
Some? None?
They’re different
than high order
functions
48. Mutation is the exception and not the rule.
Functions r first class citizens.
Learning FP
is key to
understanding
Scala
Use of recursion to
produce results rather
than iteration.
56. George Boole (1815 - 1864)
Aristotle’s algebraic logic was in
prose. I translated it to symbols!
true = 1
false = 0
and = product (AxB)
or = sum(A+B)
57. Augustus De Morgan (1806 - 1871)
All logical operations can be
expressed in terms of and, or, and
not.
a ∧ b = ¬ ( (¬ a) ∨ (¬ b) )
a ∨ b = ¬ ( (¬ a) ∧ (¬ b) )
58. Friedrich Frege (1848 – 1925)
1. If the tree is still on the
power line, then we have no
power.
2. The tree is still on the
power line.
3. Therefore, we have no power.
I created Predicate Logic, studied
the use of functions in logic and was
the first to use currying!
Predicate Logic
{ a ⇒ b, b } ⊢ b
59. Lewis Carroll (1832 –1898)
Some FP libraries reference Lewis
Carroll’s work … ex: FantasyLand
I wrote Alice in Wonderland!
...maintaining a balance between sense
and nonsense, remaining logical, even
though it appeared at times to be
completely illogical.
60. Alfred Whitehead and Bertrand Russell (1903) ● Barbers Paradox
● Wrote a 450-page proof
to show that 1 + 1 = 2
You’re Frege’n
wrong!
Get your head
out of your
ass!
61. Moses Schonfinkel (1889–1942)
I invented combinatory logic.
A combinator is a higher order function
that uses only function application and
earlier defined combinators to define a
result from its arguments.
This replacement technique reduced
multiple function arguments to a single
argument, and was later known as currying.
62. Haskell Curry - 1927 I formalized combinatory logic,
creating The Lambda Calculus, where
lambda expressions represent
functional abstractions are
replaced by a limited set of
combinators.
Is that
where …
comes from?
63. Gerhard Gentzen (1936)
I used sequent calculus
(a series of true
statements) to build
arguments according to
rules and procedures of
inference making zero or
more assertions.
64. Alonzo Church (1930)
Kleene & Rosser
…I can improve
upon Principia
Mathematica with
effectively
computable
functions
It’s
non-terminating
Try again!
65. Kleene & Rosser
Alonzo Church (1930)
Simply Typed Lambda Calculus is
a typed system with high order
functions.
66. Alan Turing (1950) My Turing Machine can
compute anything your
Lambda Calculus can!
...using loop statements
and goto statements,
i.e., not recursion.
67. MacLane and Eilenberg (1945) We introduced the
concepts of categories,
functors, and natural
transformations.
…and composition of
maps that preserves
mathematical
structure!
69. Curry-Howard-Lambek Correspondence (1969)
We discovered the one-to-one
correspondence between objects in
category theory, propositions in
logic, and types in programming
languages.
78. Moggi, Wadler, Jones (1991)
We need a framework to understand
how data flows in our apps. Given a
category C and an endomorphic
functor f with an object A …
Let’s actually use Monads in
Haskell to chain functions, handle
side effects, concurrent
processing, logging and more!
79. Gibbons, Oliveira (2006) We explored an FP solution to
the OOP iterator pattern.
Using imperative iterations
patterns we can return
transformed list of elements
the same shape!
95. ISOmorphic Equations
(C,A) x (C,B) = (C, AxB)
(A,C) x (C,B) = (A+B, C)
(C x A,B) = (C, [A⇒B])
Laws of exponents
AC
x BC
= (AxB)C
CA
x CB
= C(A+B)
B(CxA)
= (BA
)C
I see the
correspondence!
102. Haskell code
humanize b = if b then "yes" else "no"
emphasize str = str ++ "!"
compose g f = x -> g (f x)
emphasizeHumanize = compose emphasize humanize
emphasizeHumanize True
=> "yes!"
emphasizeHumanize False
=> "no!"
153. Imperative go
func SumLoop(nums []int) int {
sum := 0
for _, num := range nums {
sum += num
}
return sum
}
Recursive go
func SumRecursive(nums []int)
int {
if len(nums) == 0 {
return 0
}
return nums[0] +
… SumRecursive(nums[1:])
}
154. Imperative go
func loop(s []int,
… b *testing.B) {
for n := 0; n < b.N; n++ {
SumLoop(s)
}
}
Results: It took 46 ns/op.
Recursive go
func recursion(s []int,
… b *testing.B) {
for n := 0; n < b.N; n++ {
SumRecursive(s)
} }
Results: It took 178 ns/op.
Too slow!
156. Use FP for Monadic
workflow control.
Also checkout
Gleam.
157. References
Revenge of the Nerds
http://www.paulgraham.com/icad.html
Are Design Patterns Missing Language Features
http://wiki.c2.com/?AreDesignPatternsMissingLanguageFeatures
Embracing Functional Programming in Ruby
https://kellysutton.com/2017/09/13/embracing-functional-prog
ramming-in-ruby.html
169. If I could edit this video, I’d mention that today, depending on the
application, matrix computations are likely to be much faster using an
imperative language like C. However, if we are ever fortunate enough to
see Tail Call Optimization (TCO) in Go, then Go might be a viable option,
especially given its concurrent programming features. TCO would open
up a lot of opportunities for Go programmers; that way, we wouldn’t have
to pay such a high price for recursion in Go. - Tom
I’ll smile
more in future
presentations
:-)