Functional programming in F# The Why, What and How
Back in the days... ISWIM λ 1958 LISP 1966 1930-ish 1962 APL 1973 ML 2007 1977 FP Clojure 2005 F# 1986 Erlang 2003 Scala 1988 Haskell Ocaml 1996
Some definitions Program Data - Logic - Control Declarative Logic - Referential transparency Imperative Logic - Control - Side effects
Functional programming language Declarative First class λ Higher-Order Immutability Functions
The PAIN of imperativeness Screwupability Shared mutable states
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
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 []
FP demand UK Clojure Scala F# Erlang
Real-world uses F# Svea Ekonomi, Microsoft (Halo), Credit Suisse, Prover Haskell AT & T, Scrive Erlang Ericsson, Klarna, Basho, Facebook Lisp Yahoo Store Scala Twitter, LinkedIn
Why F#? Functional + OO + .NET + Open Source => The Most Powerful Language In The WORLD! Scala-crowd goes: O rly? Lisp-crowd goes: F-what?
F# “F# is a practical, functional-first language that lets you write simple code to solve complex problems"
Complex Simple static Tree<KeyValuePair<A, bool>> DiffTree<A>(Tree<A> tree, Tree<A> tree2) { return XFoldTree( (A x, Func<Tree<A>, Tree<KeyValuePair<A, bool>>> l, Func<Tree<A>, Tree<KeyValuePair<A, bool>>> r, Tree<A> t) => (Tree<A> t2) => Node(new KeyValuePair<A, bool>(t2.Data, ReferenceEquals(t, t2)), l(t2.Left), r(t2.Right)), x1 => y => null, tree)(tree2); }
Complex Simple Tree<KeyValuePair<A, bool>> DiffTree<A>(Tree<A> tree, Tree<A> tree2) { XFoldTree( (A x, Func<Tree<A>, Tree<KeyValuePair<A, bool>>> l, Func<Tree<A>, Tree<KeyValuePair<A, bool>>> r, Tree<A> t) => (Tree<A> t2) => Node(new KeyValuePair<A, bool>(t2.Data, ReferenceEquals(t, t2)), l(t2.Left), r(t2.Right)), x1 => y => null, tree)(tree2); }
Complex Simple DiffTree ( tree, tree2) { XFoldTree( ( x, l, r, t) => (Tree<A> t2) => Node(new KeyValuePair<A, bool>(t2.Data, ReferenceEquals(t, t2)), l(t2.Left), r(t2.Right)), x1 => y => null, tree)(tree2); }
Complex Simple DiffTree ( tree, tree2) { XFoldTree( ( x, l, r, t, t2) => Node(new KeyValuePair<A, bool>(t2.Data, ReferenceEquals(t, t2)), l(t2.Left), r(t2.Right)), x1 => y => null, tree)(tree2); }
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; }
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
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
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
(Function) values in F# let ten = 10 let square x = x*x let squareList = List.map (fun n -> n*n) let addThree = (+) 3
(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
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
F# data types Algebraic Data Types + *
F# data types - Union type Shape = | Circle of float | Rectangle of float * float | Triangle of float * float
F# data types – Recursive union type BinTree = | Leaf of int | Node of BinTree * BinTree
F# data types - Option type Option<'a> = | Some of 'a | None
F# data types - Option public Document getDocByID(int id); VS val getDocByID : int -> Document option
F# data types - Option let res = match getDocByID id with | None -> …handle not found… | Some(d) -> …do something with d…
F# data types - List type List<'a> = | Nil | Cons of 'a*List<'a> Nil + 'a*List<'a>
F# data types - List let l1 = ["a"; "list"; "of"; "strings"] let l2 = "a"::"consed"::"list"::[] let l3 = [1..42] let l4 = [for i in l3 -> i*i]
Higher-order functions let rec double l = match l with | [] -> List.empty | h::t -> h*2::double t
Higher-order functions let rec length (l:string list) = match l with | [] -> List.empty | h::t -> h.Length::length t
Higher-order functions let rec map f l = match l with | [] -> List.empty | h::t -> f(h)::map t
Higher-order functions map (fun x -> 2*x) list map (fun (x:string) -> x.Length) list
Pipelining h(g(f(x))) VS x |> f |> g |> h Pipeline operator
Function composition let f x = h(g(x)) VS let f = g >> h Composition operator
Function composition let double_then_sum = List.map ((*)2) >> List.reduce (+)
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
F# 3.0 • Type Providers • Query Expressions • Triple-quoted strings
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
So... Complex vs Simple Spaghetti vs Composability λ = Future? Headache vs Fun Lots of plumbing vs Logic
Jayway christian.jacobsen@jayway.com @chribben Functional Programming Sthlm User Group Jayway seminars Øredev

Functional programming in f sharp

  • 1.
    Functional programming inF# The Why, What and How
  • 2.
    Back in thedays... ISWIM λ 1958 LISP 1966 1930-ish 1962 APL 1973 ML 2007 1977 FP Clojure 2005 F# 1986 Erlang 2003 Scala 1988 Haskell Ocaml 1996
  • 3.
    Some definitions Program Data - Logic - Control Declarative Logic - Referential transparency Imperative Logic - Control - Side effects
  • 4.
    Functional programming language Declarative First class λ Higher-Order Immutability Functions
  • 5.
    The PAIN ofimperativeness Screwupability Shared mutable states
  • 6.
    Why not functionalprogramming? • 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 []
  • 8.
    FP demand UK Clojure Scala F# Erlang
  • 9.
    Real-world uses F# Svea Ekonomi, Microsoft (Halo), Credit Suisse, Prover Haskell AT & T, Scrive Erlang Ericsson, Klarna, Basho, Facebook Lisp Yahoo Store Scala Twitter, LinkedIn
  • 10.
    Why F#? Functional +OO + .NET + Open Source => The Most Powerful Language In The WORLD! Scala-crowd goes: O rly? Lisp-crowd goes: F-what?
  • 11.
    F# “F# is apractical, functional-first language that lets you write simple code to solve complex problems"
  • 12.
    Complex Simple static Tree<KeyValuePair<A, bool>> DiffTree<A>(Tree<A> tree, Tree<A> tree2) { return XFoldTree( (A x, Func<Tree<A>, Tree<KeyValuePair<A, bool>>> l, Func<Tree<A>, Tree<KeyValuePair<A, bool>>> r, Tree<A> t) => (Tree<A> t2) => Node(new KeyValuePair<A, bool>(t2.Data, ReferenceEquals(t, t2)), l(t2.Left), r(t2.Right)), x1 => y => null, tree)(tree2); }
  • 13.
    Complex Simple Tree<KeyValuePair<A, bool>> DiffTree<A>(Tree<A> tree, Tree<A> tree2) { XFoldTree( (A x, Func<Tree<A>, Tree<KeyValuePair<A, bool>>> l, Func<Tree<A>, Tree<KeyValuePair<A, bool>>> r, Tree<A> t) => (Tree<A> t2) => Node(new KeyValuePair<A, bool>(t2.Data, ReferenceEquals(t, t2)), l(t2.Left), r(t2.Right)), x1 => y => null, tree)(tree2); }
  • 14.
    Complex Simple DiffTree ( tree, tree2) { XFoldTree( ( x, l, r, t) => (Tree<A> t2) => Node(new KeyValuePair<A, bool>(t2.Data, ReferenceEquals(t, t2)), l(t2.Left), r(t2.Right)), x1 => y => null, tree)(tree2); }
  • 15.
    Complex Simple DiffTree ( tree, tree2) { XFoldTree( ( x, l, r, t, t2) => Node(new KeyValuePair<A, bool>(t2.Data, ReferenceEquals(t, t2)), l(t2.Left), r(t2.Right)), x1 => y => null, tree)(tree2); }
  • 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 inF# let ten = 10 let square x = x*x let squareList = List.map (fun n -> n*n) let addThree = (+) 3
  • 21.
    (Function) values inF# 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 recmerge 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
  • 23.
  • 24.
    F# data types- Union type Shape = | Circle of float | Rectangle of float * float | Triangle of float * float
  • 25.
    F# data types– Recursive union type BinTree = | Leaf of int | Node of BinTree * BinTree
  • 26.
    F# data types- Option type Option<'a> = | Some of 'a | None
  • 27.
    F# data types- Option public Document getDocByID(int id); VS val getDocByID : int -> Document option
  • 28.
    F# data types- Option let res = match getDocByID id with | None -> …handle not found… | Some(d) -> …do something with d…
  • 29.
    F# data types- List type List<'a> = | Nil | Cons of 'a*List<'a> Nil + 'a*List<'a>
  • 30.
    F# data types- List let l1 = ["a"; "list"; "of"; "strings"] let l2 = "a"::"consed"::"list"::[] let l3 = [1..42] let l4 = [for i in l3 -> i*i]
  • 31.
    Higher-order functions let recdouble l = match l with | [] -> List.empty | h::t -> h*2::double t
  • 32.
    Higher-order functions let reclength (l:string list) = match l with | [] -> List.empty | h::t -> h.Length::length t
  • 33.
    Higher-order functions let recmap f l = match l with | [] -> List.empty | h::t -> f(h)::map t
  • 34.
    Higher-order functions map (funx -> 2*x) list map (fun (x:string) -> x.Length) list
  • 35.
    Pipelining h(g(f(x))) VS x |> f |> g |> h Pipeline operator
  • 36.
    Function composition letf x = h(g(x)) VS let f = g >> h Composition operator
  • 37.
    Function composition let double_then_sum= List.map ((*)2) >> List.reduce (+)
  • 38.
    Synchronous -> Asynchronous letgetData (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
  • 39.
    F# 3.0 • TypeProviders • Query Expressions • Triple-quoted strings
  • 40.
    Summary Functional programming letsyou 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
  • 43.

Editor's Notes

  • #2 This talk is about functional programming in general and F# in particular.
  • #3 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
  • #4 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&apos;t affect the end result.Ref. http://www.csc.liv.ac.uk/~frans/OldLectures/2CS24/declarative.html#detail
  • #5 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.
  • #6 So what’s wrong with imperative programming?Due to mutability, it takes an inhumanly amount of DISCIPLINE to make STATE changes EXPLICIT.
  • #7 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.
  • #8 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&apos;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.
  • #11 F# is a pragmatic language - &quot;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
  • #12 Strong, static and parametric polymorphic type systemMulti-paradigmCurrent version 3.0
  • #13 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
  • #14 Remove keywords...
  • #15 Remove type annotations...
  • #16 Currying
  • #17 Pattern matching and tuples
  • #18 Remove brackets, semi-colons and curly braces
  • #19 Add F# keywords and create expression
  • #20 And format
  • #21 let denotes binding value to variable, i.e. not assignment (remember immutability)Function definition using letfun is the keyword for lambda function
  • #22 Nested function definitionsRecursive function
  • #24 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.
  • #25 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#
  • #26 Union types can be recursively definded.
  • #28 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?
  • #30 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
  • #31 Lists can be constructed in several different ways: by semi-colon separated listed values, using the cons operator, through sequence expression
  • #32 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.
  • #34 map is an reusable abstracted hof that hides the control structure and lets us instead focus on the logic of our program
  • #35 Declarative way of using the hof map, i.e. ”map this function to the list l”
  • #36 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
  • #42 Is functional programming the future? I hope I’ve managed to show that functional programming meansSimpler codeMore solid programsFUN