KEMBAR78
Functional programming with F# | PDF
Functional programming
with
F#
Remigiusz Koczapski
http://blog.koczapski.com
Functional programming
• Declarative instead imperative (express what do you want instead
how to get it)
• Evaluation of mathematical functions instead statements that can
change state
• Output value of a function depends on an input only. Function will
always produce the same result
• Easier to understand and more predictable behavior of the
program
Rules
• Higher-order functions - takes one or more functions as an
argument or returns a function as a result
• Pure functions (Idempotence) - have no side effect on memory or
I/O
• Recursion - functions invoke themselves
• Strict (eager) or non-strict evaluation (lazy) - arguments are/are
not evaluated if their values are not necessary to execute a
function
• Type systems - strong compile-time type checking
• Referential transparency – assigned values are never changed
Functional Languages
• Strict
• Hope
• Rex
• …
• Non-strict
• Lisp (Clojure, Logo)
• ML (OCaml)
• F#
• R
• Mathematica
• Wolfram Language
• …
F#
• Invented in Microsoft Research
• Developed by F# Software Foundation (with Microsoft’s support)
• Open source
• OCaml implementation for .NET platform
• Functional-first language
• Object Oriented Programming support
• Interoperable with all .NET languages
• Available for Windows, Linux and OSX
F# in Visual Studio
F# syntax
let SayHello() =
printf "Hello"
[<EntryPoint>]
let main argv =
SayHello()
System.Console.ReadKey() |> ignore
0
„let” identifier and functions
• Binds identifier with value or a function
• Identifier with immutable value
• Simple one-line function
• Function with overridden types
• Function invocation
let hi = "Hello"
let Square x = x * x
let Area (length : float) (height : float) : float =
length * height
SayHello()
let rectArea = Area 2.1, 3.2
Type interface
• Statically typed language
• Type error checking at compilation step
• Strong type deduction mechanism
let ShowValue myVal =
printfn "This value is: %f" myVal
Branching and looping
• Branching – if instruction
let Greeting name =
if name = "" then
"whoever you name"
else
name
let PrintNumbers min max =
for x in min..max do
printf "%i " x
• For-in loop
• For-to/downto loop
let ForToLoop() =
for i = 1 to 10 do
printf "%d " i
• While-do loop
let LookForValue value maxValue =
let mutable continueLooping = true
let generator = new Random()
while continueLooping do
let rand = generator.Next(maxValue)
if rand = value then
printfn "nFound a %d!" value
continueLooping <- false
Arrays, lists and sequences
• Arrays – fast, fixed size, with mutable elements
• Lists – works like an array, with immutable elements
let arr = [|1; 2; 3|]
let squares = Array.init 10 (fun index -> index * index)
let myList = [2; 3; 5; 4]
arr.[1] <- 99
let even = List.filter (fun x -> x % 2 = 0) myList
• Sequences – works like IEnumerable; variable size
let smallNumbers = {0..99}
let smallNumbers2 = Seq.init 100 (fun x -> x)
Forward-pipe operator |>
• Gets previous’ instruction result as an argument of next instruction
let PrintLongWords (words : string[]) =
let longWords : string [] = Array.filter(fun w -> w.Length > 8) words
let sortedLongWords = Array.sort longWords
Array.iter(fun w -> printfn "%s" w) sortedLongWords
let PrintLongWords2 (words: string[]) =
words
|> Array.filter (fun w -> w.Length > 8)
|> Array.sort
|> Array.iter (fun w -> printfn "%s" w)
Records and option types
• Records – lightweight containers for small group of values
• option – creates nullable type
type Company =
{
Name : string
SalesTaxNumber : int option
}
let company = { Name = "HCL"; SalesTaxNumber = None }
printfn "Company %s %i" company.Name company.SalesTaxNumber.Value
let company2 = { Name = "UBS"; SalesTaxNumber = Some 12314 }
Discriminated Unions
• Discriminated Union – generalized types without object hierarchy
type Shape =
| Square of float
| Rectangle of float * float
| Circle of float
let s = Square 3.4
let r = Rectangle (2.2, 1.9)
let c = Circle (1.0)
let drawning = [|s; r; c|]
Pattern matching
• Allows to compare value with conditions
• Warning if not every case is covered
• Knows how to extract fields from type
let Area (shape : Shape) =
match shape with
| Square x -> x * x
| Rectangle(h, w) -> h * w
| Circle r -> System.Math.PI * r * r
let total = drawning |> Array.sumBy Area
let one = [|50|]
let two = [|60; 61|]
let many = [|0..99|]
let Describe arr =
match arr with
| [|x|] -> sprintf "One elem: %i " x
| [|x; y|] -> sprintf "Two elems: %i, %i" x y
| _ -> sprintf "A longer array"
Immutability and shadowing
• Values are immutable by default
• „mutable” keyword creates mutable variable
• „<-” operator allows to assign new value
• Assigning new value using „let” and „=” will shadow previous value
let ImmutabilityDemo2() =
let x = 42
printfn "X: %i" x
if 1 = 1 then
let x = x + 1
printfn "x: %i" x
printfn "X: %i" x
> ImmutabilityDemo2();;
X: 42
x: 43
X: 42
let MutabilityDemo() =
let mutable x = 43
printfn "x: %i" x
x <- x + 1
printfn "x: %i" x
> MutabilityDemo();;
x: 43
x: 44
Object Oriented Programming
• Objects are immutable by default but can be mutable
• Objects can have members, methods and constructors
• Interfaces and inheritance is supported
• Autoproperties (getters and setters)
type Person(forename : string, surname : string) =
member __.Forename = forename
member __.Surname = surname
let p1 = Person("John", "Deere")
let forename = p1.Forename type MutablePerson2(forename : string, surname : string) =
member val Forename = forename with get, set
member val Surname = surname with get, set
Unit testing in F#
[<TestCase("23:59:59", 23, 59, 59)>]
let ``is time properly parsed``(time, parsedHour, parsedMinute, parsedSecond) =
//act
let parsedTime = Time.Parse(time)
//assert
Assert.That(parsedTime.Hour, Is.EqualTo(parsedHour))
Assert.That(parsedTime.Minute, Is.EqualTo(parsedMinute))
Assert.That(parsedTime.Second, Is.EqualTo(parsedSecond))
More?
• http://fsharp.org/ - F# foundation site with tutorials
• https://fsharpforfunandprofit.com/ - F# in practice
• https://app.pluralsight.com/library/courses/fsharp-jumpstart/table-of-
contents - basics video tutorial
• https://app.pluralsight.com/library/courses/functional-architecture-
fsharp/table-of-contents - more practical tutorial
• Examples taken from „F# Jumpstart” by Kit Eason – watch here

Functional programming with F#

  • 1.
  • 2.
    Functional programming • Declarativeinstead imperative (express what do you want instead how to get it) • Evaluation of mathematical functions instead statements that can change state • Output value of a function depends on an input only. Function will always produce the same result • Easier to understand and more predictable behavior of the program
  • 3.
    Rules • Higher-order functions- takes one or more functions as an argument or returns a function as a result • Pure functions (Idempotence) - have no side effect on memory or I/O • Recursion - functions invoke themselves • Strict (eager) or non-strict evaluation (lazy) - arguments are/are not evaluated if their values are not necessary to execute a function • Type systems - strong compile-time type checking • Referential transparency – assigned values are never changed
  • 4.
    Functional Languages • Strict •Hope • Rex • … • Non-strict • Lisp (Clojure, Logo) • ML (OCaml) • F# • R • Mathematica • Wolfram Language • …
  • 5.
    F# • Invented inMicrosoft Research • Developed by F# Software Foundation (with Microsoft’s support) • Open source • OCaml implementation for .NET platform • Functional-first language • Object Oriented Programming support • Interoperable with all .NET languages • Available for Windows, Linux and OSX
  • 6.
  • 7.
    F# syntax let SayHello()= printf "Hello" [<EntryPoint>] let main argv = SayHello() System.Console.ReadKey() |> ignore 0
  • 8.
    „let” identifier andfunctions • Binds identifier with value or a function • Identifier with immutable value • Simple one-line function • Function with overridden types • Function invocation let hi = "Hello" let Square x = x * x let Area (length : float) (height : float) : float = length * height SayHello() let rectArea = Area 2.1, 3.2
  • 9.
    Type interface • Staticallytyped language • Type error checking at compilation step • Strong type deduction mechanism let ShowValue myVal = printfn "This value is: %f" myVal
  • 10.
    Branching and looping •Branching – if instruction let Greeting name = if name = "" then "whoever you name" else name let PrintNumbers min max = for x in min..max do printf "%i " x • For-in loop • For-to/downto loop let ForToLoop() = for i = 1 to 10 do printf "%d " i • While-do loop let LookForValue value maxValue = let mutable continueLooping = true let generator = new Random() while continueLooping do let rand = generator.Next(maxValue) if rand = value then printfn "nFound a %d!" value continueLooping <- false
  • 11.
    Arrays, lists andsequences • Arrays – fast, fixed size, with mutable elements • Lists – works like an array, with immutable elements let arr = [|1; 2; 3|] let squares = Array.init 10 (fun index -> index * index) let myList = [2; 3; 5; 4] arr.[1] <- 99 let even = List.filter (fun x -> x % 2 = 0) myList • Sequences – works like IEnumerable; variable size let smallNumbers = {0..99} let smallNumbers2 = Seq.init 100 (fun x -> x)
  • 12.
    Forward-pipe operator |> •Gets previous’ instruction result as an argument of next instruction let PrintLongWords (words : string[]) = let longWords : string [] = Array.filter(fun w -> w.Length > 8) words let sortedLongWords = Array.sort longWords Array.iter(fun w -> printfn "%s" w) sortedLongWords let PrintLongWords2 (words: string[]) = words |> Array.filter (fun w -> w.Length > 8) |> Array.sort |> Array.iter (fun w -> printfn "%s" w)
  • 13.
    Records and optiontypes • Records – lightweight containers for small group of values • option – creates nullable type type Company = { Name : string SalesTaxNumber : int option } let company = { Name = "HCL"; SalesTaxNumber = None } printfn "Company %s %i" company.Name company.SalesTaxNumber.Value let company2 = { Name = "UBS"; SalesTaxNumber = Some 12314 }
  • 14.
    Discriminated Unions • DiscriminatedUnion – generalized types without object hierarchy type Shape = | Square of float | Rectangle of float * float | Circle of float let s = Square 3.4 let r = Rectangle (2.2, 1.9) let c = Circle (1.0) let drawning = [|s; r; c|]
  • 15.
    Pattern matching • Allowsto compare value with conditions • Warning if not every case is covered • Knows how to extract fields from type let Area (shape : Shape) = match shape with | Square x -> x * x | Rectangle(h, w) -> h * w | Circle r -> System.Math.PI * r * r let total = drawning |> Array.sumBy Area let one = [|50|] let two = [|60; 61|] let many = [|0..99|] let Describe arr = match arr with | [|x|] -> sprintf "One elem: %i " x | [|x; y|] -> sprintf "Two elems: %i, %i" x y | _ -> sprintf "A longer array"
  • 16.
    Immutability and shadowing •Values are immutable by default • „mutable” keyword creates mutable variable • „<-” operator allows to assign new value • Assigning new value using „let” and „=” will shadow previous value let ImmutabilityDemo2() = let x = 42 printfn "X: %i" x if 1 = 1 then let x = x + 1 printfn "x: %i" x printfn "X: %i" x > ImmutabilityDemo2();; X: 42 x: 43 X: 42 let MutabilityDemo() = let mutable x = 43 printfn "x: %i" x x <- x + 1 printfn "x: %i" x > MutabilityDemo();; x: 43 x: 44
  • 17.
    Object Oriented Programming •Objects are immutable by default but can be mutable • Objects can have members, methods and constructors • Interfaces and inheritance is supported • Autoproperties (getters and setters) type Person(forename : string, surname : string) = member __.Forename = forename member __.Surname = surname let p1 = Person("John", "Deere") let forename = p1.Forename type MutablePerson2(forename : string, surname : string) = member val Forename = forename with get, set member val Surname = surname with get, set
  • 18.
    Unit testing inF# [<TestCase("23:59:59", 23, 59, 59)>] let ``is time properly parsed``(time, parsedHour, parsedMinute, parsedSecond) = //act let parsedTime = Time.Parse(time) //assert Assert.That(parsedTime.Hour, Is.EqualTo(parsedHour)) Assert.That(parsedTime.Minute, Is.EqualTo(parsedMinute)) Assert.That(parsedTime.Second, Is.EqualTo(parsedSecond))
  • 19.
    More? • http://fsharp.org/ -F# foundation site with tutorials • https://fsharpforfunandprofit.com/ - F# in practice • https://app.pluralsight.com/library/courses/fsharp-jumpstart/table-of- contents - basics video tutorial • https://app.pluralsight.com/library/courses/functional-architecture- fsharp/table-of-contents - more practical tutorial • Examples taken from „F# Jumpstart” by Kit Eason – watch here