5. The PAIN of imperativeness
Screwupability
Shared mutable states
6. Why not functional programming?
• Too low dev replacability
• Legacy code not functional
• Bad interop, few libs
• Devs find it too hard
• Customers don’t care
anyway
7. Why Functional Programming?
let sum lst = foldr (+) lst 0
let product lst = foldr (*) lst 1
let append l1 l2 = foldr cons l1 l2
let length lst = foldr (+) lst 0
let map f lst = foldr (cons << f) lst []
16. Complex Simple
DiffTree ( tree,
tree2)
{
XFoldTree(
( x, l,
r,
t, t2)
=>
let (Node(x2,l2,r2)) = t2
Node((x2,t=t2), l l2, r r2)) (fun _ _ -> Leaf) tree tree2;
}
17. Complex Simple
DiffTree ( tree,
tree2)
XFoldTree(
x, l,
r,
t, t2
=>
let (Node(x2,l2,r2)) = t2
Node((x2,t=t2), l l2, r r2)) (fun _ _ -> Leaf) tree tree2
18. Complex Simple
let DiffTree ( tree,
tree2) =
XFoldTree(fun
x, l,
r,
t, t2
->
let (Node(x2,l2,r2)) = t2
Node((x2,t=t2), l l2, r r2)) (fun _ _ -> Leaf) tree tree2
19. Complex Simple
let DiffTree(tree, tree2) =
XFoldTree(fun x, l, r, t, t2 ->
let (Node(x2,l2,r2)) = t2
Node((x2,t=t2), l l2, r r2)) (fun _ _ -> Leaf) tree tree2
20. (Function) values in F#
let ten = 10
let square x = x*x
let squareList = List.map (fun n -> n*n)
let addThree = (+) 3
21. (Function) values in F#
let outer x =
let inner y =
printfn "outer + inner = %d" (x + y)
inner 21
let rec sum list =
match list with
| [] -> 0
| head::tail -> head + sum tail
22. Pattern matching
let rec merge l1 l2 = Parallel pattern
match l1, l2 with OR pattern
| [], xs | xs, [] -> xs
| x::xs', (y::_ as ys) when x <= y ->
x::merge xs' ys
| xs, y::ys' -> y::merge xs ys'
Named pattern Guarded pattern
38. Synchronous -> Asynchronous
let getData (url:string) =
let r = WebRequest.Create(url)
let resp = r.GetResponse()
use stream = resp.GetResponseStream()
use reader = new StreamReader(stream)
let data = reader.ReadToEnd()
data
40. Summary
Functional programming lets you
Focus on the problem and less on noise
Write consice and readable code
Create composable programs
F# gives you
Access to the .NET framework
Cross-platform
Multiparadigm for solving real-world problems
41. So...
Complex vs Simple
Spaghetti vs Composability
λ = Future?
Headache vs Fun
Lots of plumbing vs Logic
This talk is about functional programming in general and F# in particular.
This man, Alonzo Church, invented Lambda Calculus which is a formal theory for functionality.Many of the languages depicted here represents family of languages so for example LISP has a number of derivatives such as CLISP, Scheme, Clojure and ML has Standard ML, CAML, OCAML and F#LISP (Conditional expr, Cons cells, Garbage collection, S-expressions)APL doesn’t rely on lambda expressionISWIM (if you see what I mean). It’s interesting to see that it could’ve been a description of F# (infix, let where, Indentation). Invented by Peter Landin (also the inventor of the first VM and the expression ’syntactic sugar’)ML uses Hindley-Milner type inference and parametric polymorphism, abstract data typesFP created by John Backus (creator of Fortran) who gave the ”Can Programming Be Liberated from the von Neumann Style? A Functional Style and Its Algebra of Programs”Miranda has list comprehensions and possibility to convert infix operators to functionsOcaml is multi-paradigm in that it combines OO and FuncScalaF# is a Ocaml dialectClojure is a LISP dialect running on JVM and CLR with built in support for concurrency
In declarative programming style focus is on the logic (the what) and control is handed to the language.In imperative programming style both control and logic is the responsibility of the programmer.Side effects = state changes may occurReferential transparency = an expression may be substituted by its value and it won't affect the end result.Ref. http://www.csc.liv.ac.uk/~frans/OldLectures/2CS24/declarative.html#detail
The definition of a functional programming langugage is a bit vague but some traits that most fp languages support are...A lot of langugages support a functional programming style like Javascript, C#, C++ etc. so you could say there’s a purity scaleDeclarative style means that you describe the solution to the problem instead of what steps needs to be performed to solve the problem. Expressions are used for building the program instead of statements.Referential transparency means that what you declare is written in stone. You can refer to the stones in order to create new data structures but you can’t change it. Values are thus immutable.Functions are first class citizens meaning that they can be treated as any other value, i.e. they can passed to other functions as arguments and be returned from functions.Since we want to use decalrative style we can’t really use while and for loops as control mechanisms for iterating over data structures. Instead, recursion is utilized.
So what’s wrong with imperative programming?Due to mutability, it takes an inhumanly amount of DISCIPLINE to make STATE changes EXPLICIT.
Some arguments raised against fp, however:The leap from Java/C# to Scala/F# isn’t that big; there’s a different way of thinking but devs like to think.Interop/few libs is not a valid argument for Scala/F#Customer do care about getting new functionality fast and which is robust.
There are many good reasons: More concise and readable code Fewer bugs due to immutability Easier to reason about code due to referential transparency and therefore easier to prove correctness which leads to better optimizations by compiler Programmer effeciency Easier to parallelize etcBut apart from these reasons: It's fun! It bends your mind into thinking differently (if you come from the oo/imperative world)One of the strongest benefits is that it lends it self to modular programs through composability. Here are some examples of how we can compose functions using just a few simple primitives.
F# is a pragmatic language - "write simple code to solve complex problems“Interop with .NET’s CLI makes it very powerfulThe fact that a large company supports it makes it a good choice
Strong, static and parametric polymorphic type systemMulti-paradigmCurrent version 3.0
C#-programmers sometime find F#’s syntax hard to decipher...This is a rather complex function in C# with pretty low readability, somewhat due to strange formatting, but mainly due to ”noise” from type annotations. It calculates the difference between two tree structures
Remove keywords...
Remove type annotations...
Currying
Pattern matching and tuples
Remove brackets, semi-colons and curly braces
Add F# keywords and create expression
And format
let denotes binding value to variable, i.e. not assignment (remember immutability)Function definition using letfun is the keyword for lambda function
Nested function definitionsRecursive function
In functional languages algebraic data types are often used as data carriers (all CLI types are of course available as well). They are types composed by other types.The two most common classes are the sum type and the product type.
A union is a sum type that takes the shape of one of its composed types.It can be compared to a object hierarchy in the OO paradigm and in fact, the compiler creates a base class and subclasses for each construct.The correspondance to method dispatching is done by using pattern matching in F#
Union types can be recursively definded.
In C# for example a returned reference object might be null but it’s easy to forget to check this case. When option type is used in a match expression then the compiler issues a warning if the None-case isn’t covered.What is returned in the above case when id not found?
One of the most central types in FPSemantically eqvivalent to the sum of union and a product type. In F# Nil is [] and Cons (hd*tl) is hd::tl
Lists can be constructed in several different ways: by semi-colon separated listed values, using the cons operator, through sequence expression
Functions as values (first-class functions) makes it possible for a function to take other functions as an arguments and/or return a function. Such functions are called higher-order functions.Higher-order functions allows us to build abstractions and makes it possible to write declarative code since the control structure is hidden in these functions. Examples are map, fold, reduce, filter etc.
map is an reusable abstracted hof that hides the control structure and lets us instead focus on the logic of our program
Declarative way of using the hof map, i.e. ”map this function to the list l”
Pipelining lets you pipe data in the ”x-direction” instead of in the ”z-direction” which makes it more readable.It also benefits type inference
Is functional programming the future? I hope I’ve managed to show that functional programming meansSimpler codeMore solid programsFUN