Pragmatic Functional Programming
Programming is hard, and humans are bad at it
Scope
-
Introduction to functional programming
- especially as it applies to C#
- Terms and techniques
- Practical advice for functional programming in C#
Brief C# primer
-
generics
-
Func<> and Action<>
- lambdas and closures
Generics
class or method with a Type parameter in angle brackets
Consuming:
-
List<int> numbers;
-
var inf = Infinity<DateTime>();
Writing generic methods
Type parameter after the method name.
public List<T> Contain<T>(T a, T b)
{
var result = new List<T>();
result.Add(a);
result.Add(b);
return result;
}
Call the type whatever you want.
Can have multiple types, separated by commas.
Every instance of the type name refers to that type.
Generic classes
The entire class is parameterized by the type.
Put the type after the class name.
public class ConfigManager<T> where T : class
{
private T config;
public T GetConfig() { ... }
private void LoadConfig() { ... }
}
Code as data
Action and Func are types used to refer to some method or delegate.
Action's return type is void
Func returns its last type parameter
example:
Func<string, int> takes a string and returns an int
Action<bool> takes a bool and returns void
Code as data
public bool IsHappy(Person p) { return p.Happiness > 75; } Func<Person, bool> happyTester = IsHappy;
happyTester(bob);
Lambdas
A lambda is a shortcut for making code without making a method.
Func<int, bool> isAdult = (int age) =>
{
return age > 17;
};
equivalent:
Func<int, bool> isAdult = age => age > 17;
Closures
A closure is any lambda/delegate which "closes over" or "captures" things in its scope.
var limit = 0.04;
Func<float, bool> aboveLimit = bac => bac > limit;
limit is a local variable, but aboveLimit captures it for its own use.
Even if limit goes out of scope, aboveLimit can still use it.
Closures in C# are by reference, so the captured values can be changed and those changes will be reflected.
What is Functional Programming?
programming by composing pure functions
both:
-
as a paradigm
-
languages that facilitate the paradigm
What is a paradigm?
style
informed by language
What are some examples?
- imperative
- object oriented
- declarative
- functional
- etc
What's Functional Programming Like?
What's a function?
a "pure" function is a map of inputs to outputs
Big whoop
public void DoubleNumbers(int[] list)
{
for (int i = 0; i < list.Length; i++)
{
list[i] = list[i] * 2;
}
}
Referential Transparency
- changing function arguments
- accessing class members
- changing a static variable
- reading or writing to disk
- talking over the network
That seems useless
Can I do anything at all?
You can compute values and return them.
Immutability
immutability: objects cannot change
Have you ever tried to do this:
string firstName = firstNameField.Text;
firstName.ToLower(); //this does nothing
First-class functions
functions as variables / values
public IList<int> YearsUntilDeath(IList<Person> people) { Func<Person, int> death = (Person p) =>
{
return 70 - p.Age;
};
return people.Select(x => death(x)).ToList(); }
If a function is a value...
pass a function as an argument
public string DecodeMessage(string message, Func<string, string> decoder)
{
return decoder(message);
}
public Func<int, int> GetEmbiggener()
{
Func<int, int> embiggener = (int x) =>
{
return x * 100;
};
return embiggener;
}
Higher order functions
fancy name for a function that either:
-
takes a function as a parameter
-
returns a function
students.Select(x => x.Name);
IEnumerable<U> Select<T,U>(this IEnumerable<T> source, Func<T,U> map)
Looping
Immutability means you can't change things.
Not even a loop index: i++
Then how do you loop through an array?
Recursion.
public int Max(int[] nums) {
if(nums.Length < 2) return nums.Head; var maxTail = Max(nums.Tail); return maxTail > nums.Head ? maxTail : nums.Head; }
That's stupid
don't bother
not practical in C#
practice pragmatism
Type inference
C# has local type inference
var x = 10;
functional programming languages usually do better
var list = [];
var person = new Person();
list.Add(person);
function Add(a, b) {
a + b
}
Tuples
two or more values
public Tuple<string, Gender, FavoriteColor> WhoAreYou()
{
return Tuple.Create("Ross", Gender.Male, Color.All);
}
What are some functional programming languages?
-
Haskell
-
Clojure
-
Scala
-
F#
-
Lisp
-
Scheme
-
OCaml
- Erlang
Evaluation models
public bool IsMoreThanTen(int n)
{
if (n > 10)
true
else
false
}
Algebraic data types
discriminated union / tagged union
type Shape {
Circle(Point, float),
Rectangle(Point, Point)
}
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)
}
}
What is functional programming?
programming by composing pure functions
in a declarative style
often using immutable values
usually with a rich type system
What's the point
simple things that compose well
easier to write reusable code
promotes correct code
especially effective in the small scale
promotes readability and testability
Simplicity
simple vs easy
complex:
com - "with"
plectere - "to weave, braid, entwine"
Applying FP concepts to C#
Try to avoid:
-
storing things in class members
-
modifying method arguments
-
modifying local variables
-
interleaving things unnecessarily
Applying FP concepts to C#
- single responsibility
- don't repeat yourself
- small, composable functions
-
separate code and data
- separate everything!
Be pragmatic
Functional programming doesn't always make sense
Make a judgment call
Incorporate it slowly into your toolbox
Works best when computing values or shuffling data around
Works poorly when accessing resources:
- web requests
-
database access
"Borders"
Pure functional programming is not practical in C#
Do what you can and glue the rest
Monad
-
some type M<T>
-
constructor for M
-
Bind function
Monad
Bind signature:
M<TResult> Bind<TSource, TResult>(M<TSource> m, Func<TSource, M<TResult>> f)
Bind lets you operate on a wrapped T by passing a function, while the monad takes care of whatever logic it abstracts.
Examples in C#:
- Nullable<T>
- optional value
- IEnumerable<T>
- zero or more sequential, lazy values
Explore:
-
Real World Functional Programming (Petricek)
-
Wikipedia - Functional Programming
- learnxinyminutes.com/docs/fsharp/
- The Marvels of Monads
-
www.tryfsharp.org/
Pragmatic Functional Programming
By Ross Murray
Pragmatic Functional Programming
- 3,808