Introduction to Functional Programming
Ross Murray
- Graduated from Southeastern in 2011
- First programmed in GW-BASIC on a Tandy 1000
- I like
- colors
- games
- programming
- people
- I have no idea what I'm doing
- Please interrupt with questions
Scope
- Broad survey of functional programming
- Examples
- Relate topics to C#
- Practical applications
What is functional programming?
Two things:
- A programming paradigm
- A type of programming language
Programming paradigms
A programming paradigm is a style of programming, like a movie genre
- Imperative
- Object-oriented
- Declarative
- Event-driven
- Contstraint programming
- Agent-oriented
- Reactive
They're not always mutually exclusive
Imperative programming
- A sequence of statements
- State and control flow
- Variables, conditionals, loops
- Procedures
- Basic abstraction over machine code
int i = 10;
int s = 8;
int p = 29;
while(i > 0) {
p = p + s;
if(i < 5)
s = i +4;
i = i - 1;
}
memrcv(p);
Object-oriented programming
- Objects, with state and behavior
- Message-passing
- Polymorphism and dynamic dispatch
- Information hiding
interface Animal
Speak()
Eat()
class Dog
sustained: boolean
Speak(): "Woof!"
Eat(): sustained = true
fn main()
Animal a = new Dog()
a.Speak()
Declarative programming
- Contrasted with imperative programming
- Declare truths instead of giving instructions
- Say what you want, not how to get it
- Minimize side-effects
SELECT Book.title AS Title,
COUNT(*) AS Authors
FROM Book
JOIN Book_author
ON Book.isbn = Book_author.isbn
GROUP BY Book.title;
Functional programming paradigm
- A subset of declarative
- Core tenets:
- Higher-order functions
- Referential transparency
- Immutability
- Powerful type systems
let SumOfSquares n =
[1..n]
|> List.map (fun x -> x*x)
|> List.sum
SumOfSquares 5
Core concepts
Quick primer on some terms
- Expressions
- Functions
- Type systems
- First class functions
What's an expression?
Something which can be evaluated to produce a value.
1099 // int
String.Format("{0}!", age) // string
x => x + 10 // Func<int, int>
(length > 0) // bool
Statements are expressions which either evaluate to void, or whose value is ignored by using a semi-colon.
var x = 400; // 400, but ignored
Console.WriteLine("void"); // void
What is a function?
A "pure" function is a map of inputs to outputs
No side effects. Just output.
Type systems
A set of rules imposed on a program. The program is not correct if the rules are violated
- Static vs Dynamic
- Structural vs Nominal
- You can put anything in the type system
- Linear / Unique types
- Lifetime
First-class functions
Treating functions like any other value
- Assign a function to a variable
- Pass a function to another function
- Return a function from a function
let double n = n * 2
let ten = double 5
let twenty = double ten
C# function types
Action and Func are types in C# that describe code
Func<A,R> takes an A, returns an R
Action<A,B> takes an A and B, returns void
public double Whatever(string s, int i) { ... }
Func<string, int, double> foo = Whatever;
Action<string> bar = Console.Writeline;
Func<string, string> = File.ReadAllText;
Higher order functions
Fancy term for a function that either:
- Takes a function as a parameter
- Returns a function
Example
students.Select(x => x.Name);
Signature of Select
IEnumerable<U> Select<T,U>(this IEnumerable<T> source, Func<T,U> map)
Referential transparency
An expression is referentially transparent if replacing the expression with its evaluation does not alter the program.
cos(1.2) // 0.362357754476674
"foo" + "bar" // "foobar"
"Mixed Case".ToLower() // "mixed case"
Given the same inputs, it must always produce the same output, with no side-effects.
File.ReadAllText(@"C:\temp\foo.txt") // reads from disk
Referential transparency
No:
- Altering function arguments
- Any sort of I/O (disk, network)
- Accessing class members
- Changing a static variable
- etc
Immutability
Means things don't change (mutate)
Immutability is a key tool for simplicity
String s = "one";
s.ToLower(); // does nothing.
DateTime d = DateTime.UtcNow - TimeSpan.FromMinutes(200);
Some immutable types in C#
- string
- DateTime
- Guid
- int
Some FP languages
- Clojure
- dynamically typed
- focus on immutability and meta-programming
- Lisp syntax
- main impl: JVM, javascript
- Haskell
- "academic" language
- focus on referential transparency and types
- de facto lingua franca
- main impl: native
Some FP languages
- Scala
- Java++
- multi-paradigm
- Netflix, Twitter
- main impl: JVM
- F#
- multi-paradigm
- main impl: CLR
- Erlang
- dynamically typed
- focus on concurrency and stability
- whatsapp, facebook chat
- main impl: Erlang VM
Common FP language tools
- Algebraic data types / tagged unions
- Pattern matching
- Monads
- Tuples
- Type inference
- Anonymous functions
Algebraic data types
type Shape {
Circle(Point, float),
Rectangle(Point, Point)
}
Discriminated union / tagged union
Alternative to class hierarchies
Pattern matching
let rec factorial n =
match n with
| 0 -> 1
| _ -> n * factorial (n - 1)
Kind of like a powerful switch statement
Used to destructure types (ADTs, tuples)
Compile-time checking
Can have guards and wildcards
Pattern matching
public float Area(Shape sh) {
match sh {
Circle(_, radius) => PI * radius * radius,
Rectangle(Point{x,y}, Point{x2,y2}) => (x2 - x) * (y2 - y)
}
}
Easier to add functionality, harder to add new types
Monads
C# examples: Nullable<T>, IEnumerable<T>
A design pattern for abstracting some functionality over a type
Wraps the type and provides indirect access via functions
Common abstraction method in FP languages
Functional programming
composing mostly pure functions
in a declarative style
often using immutable values
and a rich type system
What's the point?
Simple things that compose well
Easy to write reusable code
Easy to test and reason about
Especially effective in the small scale
Realistic takeaway
- Simplicity promotes correctness and readability
- Most complexity hides between components, or in hidden assumptions
- Pure functions and immutability enforce simple APIs and interactions
- Let the type system catch errors whenever possible
- Don't be afraid to use functions as values if it simplifies your API
Structuring C# (opinions)
- Separate data and behavior.
- Most code can go in "service" classes which have no fields or properties, only pure functions (maybe a logger).
- Most data types don't need any methods or private members.
- Classes that need to store state can usually be limited to just a few private members. Separate unrelated functionality.
- Avoid inheritance whenever possible, especially for deduplication.
Structuring C# (opinions)
- Lean heavily on LINQ
- Pretend things are immutable, especially containers
- Make new things instead of changing existing ones
- Single responsibility principle, dependency injection
- Be pragmatic. Don't rush out and change everything
introduction to functional programming
By Ross Murray
introduction to functional programming
- 1,711