Functional Programming
Fundamentals
Elements of Functional Programming
March 30, 2010 Shahriar Hyder 1
Kaz Software Ltd.
”Life is too short for imperative
programming”
John Hughes
March 30, 2010 Shahriar Hyder 2
Kaz Software Ltd.
Productivity
“
It’s really clear that the imperative style of
programming has run its course. ... We’re sort
of done with that. … However, in the
declarative realm we can speculate a 10x
improvement in productivity in certain
domains. -Anders Hejlsberg
C# Architect
(from his MIX07 keynote)
”
March 30, 2010 Shahriar Hyder 3
Kaz Software Ltd.
Origins
March 30, 2010 Shahriar Hyder 4
Kaz Software Ltd.
Origins
functional programming emerged slightly by accident from several
sources
–– symbolic
symbolic logic,
logic, specifically the l-calculus
specifically the l-calculus (A.Church
(A.Church 1930s)
1930s) and
and
combinatory
combinatory logic
logic (H.Curry
(H.Curry 1930s)
1930s)
λop.λx.(op
λop.λx.(op xx x)x)
(λop.λx.(op
(λop.λx.(op xx x))
x)) (+)
(+) 21
21 == (λx.((+)
(λx.((+) xx x))
x)) 21
21 == (+)
(+) 21
21 21
21 == 42
42
–– the
the symbolic
symbolic manipulation
manipulation strandstrand of
of Artificial
Artificial Intelligence,
Intelligence, or
or rather:
rather: LISP
LISP
(J.McCarthy
(J.McCarthy 1960)
1960)
–– pseudo-code
pseudo-code for for CS
CS publications,
publications, ISWIM
ISWIM (P.Landin
(P.Landin 1966)
1966)
–– support
support languages
languages for for logic
logic and
and mathematics,
mathematics, e.g. e.g. LCF’s
LCF’s metalanguage
metalanguage ML ML
(Milner
(Milner et.
et. al.
al. 1970s)
1970s)
–– OCaml
OCaml –– 1996
1996
–– F#
F# (and
(and parts
parts ofof C#)
C#) –– 2002
2002
March 30, 2010 Shahriar Hyder 5
Kaz Software Ltd.
λ-calculus Building Block
• Anonymous functions Support
– JavaScript
– PHP 4.0.1 – PHP 5.2.x (kinda)
– PHP 5.3 (more kinda)
– C# 2.0
– Java – Hardly any support. Anonymous Classes to use
Closures. Java also supports another form of classes,
which are called inner (or nested) classes. These are
defined in the body of an enclosing class and have full
access to each and every instance variable of the
enclosing class, thus resembling standard function
closures.
March 30, 2010 Shahriar Hyder 6
Kaz Software Ltd.
Fundamentals of FP Languages
• The objective of the design of a FPL is to mimic
mathematical functions to the greatest extent possible
• The basic process of computation is fundamentally
different in a FPL than in an imperative language
– In an imperative language, operations are done and the
results are stored in variables for later use
– Management of variables is a constant concern and source
of complexity for imperative programming
• In an FPL, variables are not necessary, as is the case in
mathematics
March 30, 2010 Shahriar Hyder 7
Kaz Software Ltd.
What is object-oriented programming?
• Object-oriented programming is a style of
programming that enables you:
- Reuse code (via classes)
- Eliminate bugs (via encapsulating, data
hiding)
March 30, 2010 Shahriar Hyder 8
Kaz Software Ltd.
What is functional programming?
• Functional programming is a style of
programming
that enables you:
- Re-use code (via function composition)
- Eliminate bugs (via immutability)
March 30, 2010 Shahriar Hyder 9
Kaz Software Ltd.
Moore’s Law Ran Out!
March 30, 2010 Shahriar Hyder 10
Kaz Software Ltd.
“Software gets slower faster than hardware gets
faster”
--Wirth’s Law
March 30, 2010 Shahriar Hyder 11
Kaz Software Ltd.
Von Neumann syndrome
• For most applications in massively parallel computing systems with
thousands or tens of thousands of processors the performance can be less
than hoped. Sometimes called a "supercomputing crisis" it is believed to be
due to two factors. Firstly a hardware barrier in the efficiency in moving data,
called the memory wall or von Neumann bottleneck (An inefficiency inherent
in the design of any von Neumann machine [The von Neumann architecture
is a design model for a stored-program digital computer that uses a central
processing unit (CPU) and a single separate storage structure ("memory") to
hold both instructions and data. It has a sequential architecture.] that arises
from the fact that most computer time is spent in moving information
between storage and the central processing unit rather than operating on it.
• ). Secondly a fall in programmer productivity when faced with systems that
are massively parallel, the difficulties in developing for parallelism (or thread-
level parallelism in multi-core CPUs) when previously this was not an issue.
March 30, 2010 Shahriar Hyder 12
Kaz Software Ltd.
March 30, 2010 Shahriar Hyder 14
Kaz Software Ltd.
March 30, 2010 Shahriar Hyder 15
Kaz Software Ltd.
March 30, 2010 Shahriar Hyder 16
Kaz Software Ltd.
March 30, 2010 Shahriar Hyder 17
Kaz Software Ltd.
March 30, 2010 Shahriar Hyder 18
Kaz Software Ltd.
March 30, 2010 Shahriar Hyder 19
Kaz Software Ltd.
March 30, 2010 Shahriar Hyder 20
Kaz Software Ltd.
March 30, 2010 Shahriar Hyder 21
Kaz Software Ltd.
Functional Languages
• Haskell • Scala
• Clean • Clojure
• F# • XSLT
• ML / OCaml • Erlang
• Lisp / Scheme • SQL
• Mathematica
March 30, 2010 Shahriar Hyder 22
Kaz Software Ltd.
Pure Functional Languages
• Haskell • Scala
• Clean • Clojure
• F# • XSLT
• ML / OCaml • Erlang
• Lisp / Scheme • SQL
• Mathematica
Purely functional is a term in computing used to describe algorithms, data structures or
programming languages that exclude destructive modifications (updates). According to this
restriction, variables are used in a mathematical sense, with identifiers referring to
immutable, persistent values.
March 30, 2010 Shahriar Hyder 23
Kaz Software Ltd.
Is it too hard?
March 30, 2010 Shahriar Hyder 24
Kaz Software Ltd.
The foundation
March 30, 2010 Shahriar Hyder 25
Kaz Software Ltd.
What is a function?
• y = f(x)
March 30, 2010 Shahriar Hyder 26
Kaz Software Ltd.
FP Preachings!
• Avoid Side-Effects!
Do not modify variables passed to them
Do not modify any global variable
March 30, 2010 Shahriar Hyder 27
Kaz Software Ltd.
FP Preachings!
• Avoid Mutation!
“Mutation Considered Harmful”
March 30, 2010 Shahriar Hyder 28
Kaz Software Ltd.
FP Preachings!
• Variables only assigned once
• Same input -> Same output
• Functions return values
Given a set of values in the parameter list, the
function can only have one possible result.
• No Shared State
March 30, 2010 Shahriar Hyder 29
Kaz Software Ltd.
FP Preachings!
• Does order matter?
• Order is a side effect as well..
March 30, 2010 Shahriar Hyder 30
Kaz Software Ltd.
Functional Programming
• Focus on results not process
– Emphasis is on what is to be computed not how it
Happens
• Data is immutable
• Functions are data too
• Decompose problem into ‘functions’
March 30, 2010 Shahriar Hyder 31
Kaz Software Ltd.
Data is immutable
x = x + 1;
• Why should a function in C never return a
pointer?
• Why should you make a copy of an internal
array before returning it from your class?
• Why is multi-threading so damn hard?
March 30, 2010 Shahriar Hyder 32
Kaz Software Ltd.
Why bother?
• Pure functions can be executed in parallel
without interfering with one another
• Pure functions can be “perfectly” cached
• Pure functions can be “partially” applied
• Functions can receive and return functions, for
which all of the above hold true
• Allows for greater “modularity” and
“composability”
March 30, 2010 Shahriar Hyder 33
Kaz Software Ltd.
Code!
//F# //C#
open System using System;
let a = 2
namespace ConsoleApplication1
Console.WriteLine a
{
class Program
{
static int a()
{
return 2;
}
static void Main(string[] args)
{
Console.WriteLine(a);
}
}
}
March 30, 2010 Shahriar Hyder 34
Kaz Software Ltd.
More Code!
//F# //C#
open System using System;
let a = 2
namespace ConsoleApplication1
Console.WriteLine a
{
class Program
{
static nt a()
{
return 2;
}
static void Main(string[] args)
{
Console.WriteLine(a);
}
More Noise }
}
March 30, 2010
Than Signal!
Shahriar Hyder Kaz Software Ltd.
35
Refactoring “hole in the middle”
Header() { ■ ■ ■ }
Footer() { ■ ■ ■ }
Red() { ■ ■ ■ } Factor
Factor out
out the
the differences
differences and
and the
the
Blue() { ■ ■ ■ } similarities?!
similarities?!
Foo() Bar()
{ {
Header(); Header();
Red(); Blue();
Footer(); Footer();
} }
March 30, 2010 Shahriar Hyder 36
Kaz Software Ltd.
Refactoring “hole in the middle”
FooBar(func)
{
■■■
Red() { ■ ■ ■ } func();
Blue() { ■ ■ ■ } ■■■
}
The
The “FP
“FP Way”
Way” isis to
to simply
simply pass
pass in
in an
an
implementation
implementation of of the
the “hole”
“hole” to
to be
be
filled:
filled:
FooBar( {{■■ ■■ ■});
FooBar( ■});
March 30, 2010 Shahriar Hyder 37
Kaz Software Ltd.
Example: Sorting by multiple keys
class GasResult
{
public GasResult(…) { … }
public readonly string Name;
public readonly double Price;
public readonly double Distance;
}
Problem:
Problem: You
You want
want to
to sort
sort lists
lists of
of
GasResults
GasResults by
by various
various keys.
keys.
March 30, 2010 Shahriar Hyder 38
Kaz Software Ltd.
OO Approach: Many IComparers
class GasResult
{
…
public class GasPriceComparer : IComparer<GasResult>
{ public int Compare(GasResult a, GasResult b)
{ return a.Price.CompareTo(b.Price); } }
public static GasPriceComparer GasPriceComparison =
new GasPriceComparer();
}
Array.Sort<GasResult>(results, GasResult.GasPriceComparison);
March 30, 2010 Shahriar Hyder 39
Kaz Software Ltd.
OO Approach: Many IComparers
class GasResult
{
…
public class GasNameComparer : IComparer<GasResult>
{ public int Compare(GasResult a, GasResult b)
{ return a.Name.CompareTo(b.Name); } }
public static GasNameComparer GasNameComparison =
new GasNameComparer();
}
Array.Sort<GasResult>(results,
GasResult.GasNameComparison);
March 30, 2010 Shahriar Hyder 40
Kaz Software Ltd.
OO Approach: Many IComparers
class GasResult
{
…
public class GasDistanceComparer : IComparer<GasResult>
{ public int Compare(GasResult a, GasResult b)
{ return a.Distance.CompareTo(b.Distance); } }
public static GasDistanceComparer GasDistanceComparison =
new GasDistanceComparer();
}
Array.Sort<GasResult>(results, GasResult.GasDistanceComparison);
March 30, 2010 Shahriar Hyder 41
Kaz Software Ltd.
FP Approach: Passed in lambdas
class GasResult
{
…
}
results.OrderBy<GasResult, double>(r => r.Price);
results.OrderBy<GasResult, string>(r => r.Name);
results.OrderBy<GasResult, double>(r => r.Distance);
(extension)
(extension) IOrderedSequence<TSource>
IOrderedSequence<TSource>
IEnumerable<TSource>.OrderBy<TSource,
IEnumerable<TSource>.OrderBy<TSource, TKey>
TKey>
(Func<TSource,
(Func<TSource, Tkey>
Tkey> keySelector)
keySelector)
March 30, 2010 Shahriar Hyder 42
Kaz Software Ltd.
March 30, 2010 Shahriar Hyder 43
Kaz Software Ltd.
First-class function
• In computer science, a programming language
is said to support first-class functions if it
treats functions as first-class objects.
Specifically, this means that the language
supports constructing new functions during
the execution of a program, storing them in
data structures, passing them as arguments to
other functions, and returning them as the
values of other functions.
March 30, 2010 Shahriar Hyder 44
Kaz Software Ltd.
Closure (computer science)
• In computer science, a closure is a
first-class function with free variables that are
bound in the lexical environment. Such a
function is said to be "closed over" its free
variables. A closure is defined within the scope
of its free variables, and
the extent of those variables is at least as long
as the lifetime of the closure itself..
March 30, 2010 Shahriar Hyder 45
Kaz Software Ltd.
Closures
March 30, 2010 Shahriar Hyder 46
Kaz Software Ltd.
Closure example
• Here is an example rewritten in ECMAScript (JavaScript) :
// Return a list of all books with at least 'threshold' copies sold.
function bestSellingBooks(threshold) {
return bookList.filter( function (book) {
return book.sales >= threshold;
} );
}
• A function may create a closure and return it, as in the following example:
// Return a function that approximates the derivative of f
// using an interval of dx, which should be appropriately small.
function derivative(f, dx) {
return function (x) {
return (f(x + dx) - f(x)) / dx;
};
}
• Because the closure in this case outlives the scope of the function that creates it, the variables f and dx live on after the
function derivative returns. In languages without closures, the lifetime of a local variable coincides with the execution of the
scope where that variable is declared. In languages with closures, variables must continue to exist as long as any existing
closures have references to them. This is most commonly implemented using some form of garbage collection.
March 30, 2010 Shahriar Hyder 47
Kaz Software Ltd.
Generators
/* Method that takes an iterable input (possibly an array) and
returns all even numbers. */
public static IEnumerable<int> GetEven(IEnumerable<int>
numbers) {
foreach (int i in numbers) {
if ((i % 2) == 0) {
yield return i;
}
}
}
• You may even use multiple yield return statements and the compiler will return
them in order on each iteration:
public class CityCollection : IEnumerable<string> {
public IEnumerator<string> GetEnumerator() {
yield return "New York";
yield return "Paris";
yield return "London";
}
} March 30, 2010 Shahriar Hyder Kaz Software Ltd.
48
Higher order functions
Higher-order functions are closely related to first-class
functions, in that higher-order functions and first-class functions
both allow functions as arguments and results of other
functions. The distinction between the two is subtle: "higher-
order" describes a mathematical concept of functions that
operate on other functions, while "first-class" is a computer
science term that describes programming language entities that
have no restriction on their use (thus first-class functions can
appear anywhere in the program that other first-class entities
like numbers can, including as arguments to other functions and
as their return values).
March 30, 2010 Shahriar Hyder 49
Kaz Software Ltd.
Higher order function example
//f is a function
function derivative(f) {
return function(x) {
//approximation of derivative
return (f(x + 0.00001) f(x)) / 0.00001;
}
}
March 30, 2010 Shahriar Hyder 50
Kaz Software Ltd.
Higher order function example
//evaluate derivative of x2:
var deriv_x_squared = derivative(
function(x) {
return x*x;
}
);
alert(deriv_x_squared(3)); //alerts 6ish
March 30, 2010 Shahriar Hyder 51
Kaz Software Ltd.
March 30, 2010 Shahriar Hyder 52
Kaz Software Ltd.
March 30, 2010 Shahriar Hyder 53
Kaz Software Ltd.
March 30, 2010 Shahriar Hyder 54
Kaz Software Ltd.
March 30, 2010 Shahriar Hyder 55
Kaz Software Ltd.
Map/Reduce/Filter
double CheapGasNearby(IEnumerable<GasResult> results) {
double min = double.MaxValue;
foreach (GasResult r in results) {
if (r.Distance < 5.0) {
double price = r.Price;
if (r.Name == "Safeway")
price *= 0.9;
if (price < min)
min = price;
}
}
return min;
}
March 30, 2010 Shahriar Hyder 56
Kaz Software Ltd.
Map/Reduce/Filter
double CheapGasNearby(IEnumerable<GasResult> results) {
double min = double.MaxValue;
foreach (GasResult r in results) {
if (r.Distance < 5.0) {
double price = r.Price;
if (r.Name == "Safeway")
price *= 0.9;
if (price < min)
min = price;
}
}
return min;
}
March 30, 2010 Shahriar Hyder 57
Kaz Software Ltd.
Map/Reduce/Filter
double CheapGasNearby(IEnumerable<GasResult> results) {
double min = double.MaxValue;
foreach (GasResult r in results) {
if (r.Distance < 5.0) {
double price = r.Price;
if (r.Name == "Safeway")
price *= 0.9;
if (price < min)
min = price;
}
}
return min;
}
March 30, 2010 Shahriar Hyder 58
Kaz Software Ltd.
Map/Reduce/Filter
double CheapGasNearby(IEnumerable<GasResult> results) {
double min = double.MaxValue;
foreach (GasResult r in results) {
if (r.Distance < 5.0) {
double price = r.Price;
if (r.Name == "Safeway")
price *= 0.9;
if (price < min)
min = price;
}
}
return min;
}
March 30, 2010 Shahriar Hyder 59
Kaz Software Ltd.
Map/Reduce/Filter
double CheapGasNearby(IEnumerable<GasResult> results)
{
results
.Where(r => r.Distance < 5.0)
.Select(r => r.Price * (r.Name == "Safeway" ? 0.9 : 1.0))
.Aggregate(double.MaxValue, (m, p) => p < m ? p : m));
}
.Where<GasResult>(Func<GasResult,
.Where<GasResult>(Func<GasResult, bool>
bool> predicate)
predicate)
.Select<GasResult,
.Select<GasResult, double>(Func<GasResult,
double>(Func<GasResult, double>
double> mapping)
mapping)
.Aggregate<double,
.Aggregate<double, double>(double
double>(double seed,
seed, Func<double,
Func<double, double,
double, double>
double> func)
func)
March 30, 2010 Shahriar Hyder 60
Kaz Software Ltd.
Map/Reduce/Filter
double CheapGasNearby(IEnumerable<GasResult> results)
{
results
.Where(r => r.Distance < 5.0)
.Select(r => r.Price * (r.Name == "Safeway" ? 0.9 : 1.0))
.Min();
}
.Where<GasResult>(Func<GasResult,
.Where<GasResult>(Func<GasResult, bool>
bool> predicate)
predicate)
.Select<GasResult,
.Select<GasResult, double>(Func<GasResult,
double>(Func<GasResult, double>
double> mapping)
mapping)
.Aggregate<double,
.Aggregate<double, double>(double
double>(double seed,
seed, Func<double,
Func<double, double,
double, double>
double> func)
func)
March 30, 2010 Shahriar Hyder 61
Kaz Software Ltd.
Map/Reduce/Filter
double CheapGasNearby(IEnumerable<GasResult> results)
{
(from r in results
where r.Distance < 5.0
select r.Price * (r.Name == "Safeway" ? 0.9 : 1.0)
).Min()
}
.Where<GasResult>(Func<GasResult,
.Where<GasResult>(Func<GasResult, bool>
bool> predicate)
predicate)
.Select<GasResult,
.Select<GasResult, double>(Func<GasResult,
double>(Func<GasResult, double>
double> mapping)
mapping)
.Aggregate<double,
.Aggregate<double, double>(double
double>(double seed,
seed, Func<double,
Func<double, double,
double, double>
double> func)
func)
March 30, 2010 Shahriar Hyder 62
Kaz Software Ltd.
March 30, 2010 Shahriar Hyder 63
Kaz Software Ltd.
Summary
• Pure functions
– Working without assignment
– Recursion rather than for/while/etc.
• Higher-order functions
– Power! Brevity! Beautiful!
– Hole in the middle
– Compositional
• Becoming mainstream
– Driven by concurrency
– More productivity regardless
March 30, 2010 Shahriar Hyder 64
Kaz Software Ltd.
Quiz
Is ”2+2” equal to ”4”?
March 30, 2010 Shahriar Hyder 65
Kaz Software Ltd.
Reference
• F#
http://research.microsoft.com/fsharp
• Can Your Programming Language Do This?
http://www.joelonsoftware.com/items/2006/08/01.html
• Why Functional Programming Matters
http://www.math.chalmers.se/~rjmh/Papers/whyfp.pdf
• John Backus’ 1977 Turing Award Lecture:
“Can Programming be Liberated from the von Neumann Style?”
• System.Concurrency Library
http://msdn.microsoft.com/msdnmag/issues/07/10/Futures/default.aspx
• Google MapReduce
http://labs.google.com/papers/mapreduce.html
March 30, 2010 Shahriar Hyder 66
Kaz Software Ltd.
End of the Talk
• Thank You!
Questions?
March 30, 2010 Shahriar Hyder 67
Kaz Software Ltd.