Justas Masiulis 2019

What's functional programming about

  • Immutable by default

int foo = 5;
// write some more code
...
foo = 6;
						

What's so different about functional programming

  • Immutable
  • Pure

                            int global_foo = 0;

                            int bar(int baz) {
                                global_foo += 1;
                                return global_foo + baz;
                            }
						

What's so different about functional programming

  • Immutable
  • Pure
  • Functions are primary manipulation unit

int* getFib(unsigned n) {
	int* nums = (int*)malloc(n * sizeof(int));
	if(!nums) return NULL;
 
	if(n < 0) nums[0] = 0;
        
	if(n > 1) nums[1] = 1;
        
	for(unsigned i = 2; i < n; ++i)
		nums[i] = nums[i - 2] + nums[i - 1];
 
	return nums;
}
						

So what does functional programming look like then?

A language that doesn't affect the way you think about programming is not worth knowing.

Alan J. Perlis

F# syntax basics

Variables


(* ---- simple variables ---- *)
let myInt    = 0
let myFloat  = 1.23
let myString = "456"

(* ---------- lists --------- *)
let oneToThree  = [1;2;3]
// :: adds a _single_ element to front
let zeroToThree = 0 :: oneToThree
// @ concatenates lists
let zeroToFive  = zeroToThree @ [4;5]
					

Functions


(* ---- simple function ---- *)
let add a b = a + b
let greet () = printfn "hello!"

(* ---- anonymous function -- *)
let add2 = fun a b -> a + b

let three = add 1 2
greet ()
					

Matching


let describeNumber num =
    match num with
    | 0 -> "zero"
    | _ when num < 0 -> "negative"
    | _ -> "positive non zero"
					

Records


type Human =
    { age  : int
      name : string }

let me      = { age = 20; name = "Justas" }
let olderMe = { me with age = me.age + 1 }
					

Unions


type Action =
    | Attack
    | WalkForwards of int

let displayAction a =
    | Attack -> printfn "You tried attacking an enemy"
    | WalkForward(distance)
        -> printfn "You walked forward by %i tiles" distance

displayAction (WalkForward 4)
					

Syntax sugar

simple quicksort


let rec qsort list =
    match list with
    | [] -> []
    | first::rest ->
        let s, l = List.partition (fun x -> x < first) rest
        Lists.append (qsort s) (first :: qsort l)
                        

`= function` shorthand


let rec qsort = function
    | [] -> []
    | first::rest ->
        let s, l = List.partition (fun x -> x < first) rest
        Lists.append (qsort s) (first :: qsort l)
                        

operator @


let rec qsort = function
    | [] -> []
    | first::rest ->
        let s, l = List.partition (fun x -> x < first) rest
        qsort s @ first :: qsort l
                        

Operator quirks and partial apllication


let rec qsort = function
    | [] -> []
    | first::rest ->
        let smaller, larger = List.partition ((<) first) rest
        qsort smaller @ first :: qsort larger
                        

Okay so lets take an actual problem and try to solve it

Do you still remember the fibonacci function we saw earlier?

Lets generate a sequence and then get the sum of it

C solution


int* getFib(unsigned n) {
	int* nums = (int*)malloc(n * sizeof(int));
	if(n > 0) nums[0] = 0;
	if(n > 1) nums[1] = 1;
	for(unsigned i = 2; i < n; ++i)
		nums[i] = nums[i - 2] + nums[i - 1];
	return nums;
}
int fibSum(unsigned n) {
    int *nums = getFib(n), sum = 0;
    for(int i = 0; i < n; ++i)
        sum += nums[i];
    return sum;
}
                

F# solution


let rec genFib a b = function
    | 0 -> []
    | n -> a :: genFib b (a + b) (n - 1)
let fibList n = genFib 0 1 n
let fibSum n = fibList n |> List.sum
                        

F# solution 2


let rec genFibSeq a b = seq {
    yield a
    yield! fibSeq b (a+b)
}
let fibSeq = genFibSeq 0 1
let fibSum n = fibSeq |> Seq.take n |> Seq.sum
                        

F# solution 3


let fibSeq = Seq.unfold (fun (a,b) -> Some(a + b, (b,a + b))) (0,1)
let fibSum n = fibSeq |> Seq.take n |> Seq.sum
                        

And an obligatory somewhat unreadable thing


open FParsec
let rec sum s = s |> chainl1 product (skipChar '+' >>% (+) <|> (skipChar '-' >>% (-)))
and product s = s |> chainl1 expr    (skipChar '*' >>% (*) <|> (skipChar '/' >>% (/)))
and expr    s = s |> (between (skipChar '(') (skipChar ')') sum <|> pint32)
printfn "%A" <| run sum "1+2-3/(2-1)+1"
                        

Please like share and subscribe