Functional Programming

with F#

In computer science, functional programming is a programming paradigm—a style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. It is a declarative programming paradigm, which means programming is done with expressions or declarations instead of statements.

- Wikipedia

Curse of FP

Once you understand it, you can't explain it!

Except for that you can't really understand this!

Lambda
Lambda Calculus
Lazy evaluation
Monoid
Monad
Comonad
Applicative Functor
Morphism
Endomorphism
Isomorphism
Setoid

Front end dev @Harbinger

SSE

3+ years of experience

Javascript, React, React Native

C# F# SQL Server

Microsoft Azure

GraphQL

Pillars of FP

Mathematical functions

Immutability

Functions are "things"

Types are cheap

Currying 

Partial application

Composition

Function signatures

Patterns

Mathematical functions

let add1 x = x + 1
val add1 : int -> int

Key features

Pure functions

Output never changes

No side-effects

Exactly one input and one output

Immutability

It's not that you can't change values, it's the way you do it.

Values and types are immutable by default

You "transform" the state rather than reassigning

 

Why?

Separation of logic and data

Helps reduce side-effects

Previous and new state can be compared

Increased predictability

Immutability: Example

for (int i=0; i<array.Count-1; i++) {
    array[i] = array[i] * 2
}
let data  = [1;2;3;4;5]
let data2 = List.map (fun x -> x * 2) data

With mutation

When done the right way -

type PersonalName = {FirstName:string; LastName:string}
// immutable person
let john = {FirstName="John"; LastName="Doe"}

// new person
let alice = {john with FirstName="Alice"}

Functions are "things"

Functions are just like values

They can be passed around

Functions can return functions

Functions can be stored as values

Functions have their own type

Function calls always return something

Functions are "things"

// (int -> int -> int) -> int -> int -> int   ....(1)
let binaryOperator operation num1 num2 =
    operation num1 num2

// int -> int -> int
let add num1 num2 = num1 + num2
let sub num1 num2 = num1 - num2

// int -> int -> int
let addNums = binaryOperator add
let subNums = binaryOperator sub

let a = addNums 1 2 // 3
let b = subNums 3 4 // 1

Types are cheap

FP encourages creating lots and lots of small types

Small types form together bigger types

Most suitable for Domain driven design (DDD)

 

Types in F#

Function types, The unit type, Tuples, Records, Discriminated Unions, Option types, Lists

type PersonalName = {FirstName:string; LastName:string}

// Addresses
type StreetAddress = {Line1:string; Line2:string; Line3:string }

type ZipCode =  ZipCode of string   
type StateAbbrev =  StateAbbrev of string
type ZipAndState =  {State:StateAbbrev; Zip:ZipCode }
type USAddress = {Street:StreetAddress; Region:ZipAndState}

type UKPostCode =  PostCode of string
type UKAddress = {Street:StreetAddress; Region:UKPostCode}

type InternationalAddress = {
    Street:StreetAddress; Region:string; CountryName:string}

// choice type -- must be one of these three specific types
type Address = USAddress | UKAddress | InternationalAddress

Defining domain

// Email
type Email = Email of string

// Phone
type CountryPrefix = Prefix of int
type Phone = {CountryPrefix:CountryPrefix; LocalNumber:string}

type Contact = 
    {
    PersonalName: PersonalName;
    // "option" means it might be missing
    Address: Address option;
    Email: Email option;
    Phone: Phone option;
    }

Defining domain (contd.)

A little bit about DDD

Designing world with types

Making illegal states unrepresentable

Eg. Shopping cart - Paid, Active, Empty

Currying

Breaking multi-parameter functions into smaller one-parameter functions

F# functions default to this mode

//normal version
let printTwoParameters x y = 
   printfn "x=%i y=%i" x y

//explicitly curried version
let printTwoParameters x  =    // only one parameter!
   let subFunction y = 
      printfn "x=%i y=%i" x y  // new function with one param
   subFunction                 // return the subfunction

Cool story bro. What's the use of it?

Partial Application

Baking-in some of the parameters of a function

Fire at the right moment

Example

m1 and m2 are masses of objects

G is the universal gravitational constant

r is the distance between objects

// Regardless of the planet
let calculateForce m1 m2 r =
    (G * m1 * m2) / r

// Specific to earth
let calculateForceWithEarth = calculateForce (5.972 * 10^24)

Composition

Building new functions from existing ones

Being able to call a chain of functions just once

let negate num = num * -1
let add1 num = num + 1
let sub1 num = num - 1
let mul100 num = num * 100

let composedFunc = negate >> add1 >> sub1 >> mul100

let result = composedFunc 1 // -100
var result = negate(add1(sub1(mul100(1))));

C# version

Function Signatures

A function signature can give you some idea of what it does

val testA = int -> int
val testB = int -> int -> int
val testC = int -> (int -> int)      
val testD = (int -> int) -> int
val testE = int -> int -> int -> int
val testF = (int -> int) -> (int -> int)
val testG = int -> (int -> int) -> int
val testH = (int -> int -> int) -> int

Design Patterns

Stolen from Scott Wlaschin's deck

Design Patterns in FP

Stolen from Scott Wlaschin's deck

What's the point of it all?

Making code more readable

Making code easier to reason about

Making code easier to test

Make our users happy

But FP is NOT the silver bullet!

Substantial investment of time and effort

Steep learning curve

Mathematical vocabulary

Simple things get complicated Eg. Updating array

It's ok to compromise in love and war

Functional core

Object oriented shell

Thank you

Functional programming with F#

By Mihir Karandikar

Functional programming with F#

  • 115