SlideShare a Scribd company logo
August 7, 2017
Tom Prior
www.prigrammer.com
@priortd
F# Delight
Our Sponsors
Getting started – F# interactive FSI
https://www.microsoft.com/net/download/core
dotnet new console -lang f# -o MyConsoleApp
cd MyConsoleApp
dotnet restore
code .
Create fsx file and start
executing code with f#
interactive!
Just highlight and press
Alt-Enter
The Delights
• Simplicity
• Immutability
• Pattern matching
• Encoding logic in types
• Automatic currying – all functions are one arg functions
• High level transformations and functional pipelines
Immutability – let bindings
let x = 2
Evaluated in FSI…
val x : int = 2
Will this increment x ??
Evaluated in FSI…
val x : int = 2
val it : bool = false
let x = 2
x = x + 1
Specifying Mutability
Evaluated in FSI…
val mutable y : int = 3
val it : unit = ()
x <- x + 1 //won’t compile as x not mutable.
let mutable y = 2
y <- y + 1
Tuples
let p = ("Tom", 38)
fst p
Evaluated in FSI ….
val p : string * int = ("Tom", 38)
val it : string = "Tom"
Immutability – OO Classes
type Person(name:string) =
member p.Name = name
Immutability – Records
type Person = {
Name : string
Age : int }
let p = { Name = "Tom"; Age = 56 }
Evaluated in FSI…
type Person =
{Name: string;
Age: int;}
val p : Person = {Name = "Tom";
Age = 56;}
Evaluated in FSI…
val it : string = "Tom"
//won't compile as records are immutable.
p.Name <- "Jack"
p.Name
Immutable Collections
Evaluated in FSI…
val numbers : int list = [1; 2; 3; 4]
open FSharp.Collections
let numbers = [ 1; 2; 3; 4 ]
//won't compile becuase lists are immutable
numbers.[2] <- 7
Arrays still mutable
Evaluated in FSI…
val names : string [] = [|"tom"; "eleanor"|]
val it : string = "tom"
let names = [| "tom"; "eleanor" |]
names.[0]
names.[0] <- "Myles"
names.[0]
Evaluated in FSI…
val it : string = "Myles"
Pattern matching
Evaluated in FSI…
val person : string * int = ("Tom", 38)
val name : string = "Tom"
val age : int = 38
let person = ("Tom", 38)
let (name, age) = person
Match expressions
Evaluated in FSI…
val getName : 'a * 'b -> 'a
val person : string * int = ("Tom", 38)
val it : string = "Tom"
let getName person =
match person with
| (name, age) -> name
let person = ("Tom", 38)
getName person
Pattern matching on records
Evaluated in FSI…
type Person =
{Name: string;
Age: int;}
val p : Person = {Name = "Tom";
Age = 38;}
val personName : string = "Tom"
type Person = { Name : string; Age : int }
let p = { Name = "Tom"; Age = 38 }
let { Name = personName; Age = _ } = p
Pattern matching on lists
let l = [ 1; 2; 3 ]
1
2
3
[]
//l can be re-written as
let l = 1 :: 2 :: 3 :: []
Evaluated in FSI…
val l : int list = [1; 2; 3]
val getFirst : list:'a list -> 'a
val it : int = 1
let l = 1 :: 2 :: 3 :: []
let getFirst list =
match list with // warning if not all patterns covered
| x :: xs -> x
| [] -> failwith "cannot get first on an empty list"
// you wouldn't actually do this - this would return an option
instead - will cover this shortly.
getFirst l
Discriminated Unions
type Drummer = Drummer of string
type BassPlayer = BassPlayer of string
type SaxPlayer = SaxPlayer of string
type PianoPlayer = PianoPlayer of string
type JazzBand =
| PianoTrio of PianoPlayer * BassPlayer * Drummer
| SaxTrio of SaxPlayer * BassPlayer * Drummer
| Quartet of SaxPlayer * PianoPlayer * BassPlayer * Drummer
Simplified…
let getBandLeader (jazzband: JazzBand) =
match jazzband with
| PianoTrio(PianoPlayer(ppn), BassPlayer(bassPlayerName), Drummer(dn)) -> ppn
| SaxTrio(SaxPlayer(spn), BassPlayer(bpn), Drummer(dn)) -> spn
| Quartet(SaxPlayer(spn), PianoPlayer(name), BassPlayer(bpn), Drummer(dn)) -> spn
let getBandLeader (jazzband: JazzBand) =
match jazzband with
| PianoTrio(PianoPlayer(pianoPlayerName), _, _) -> pianoPlayerName
| SaxTrio(SaxPlayer(saxPlayerName), _, _) -> saxPlayerName
| Quartet(SaxPlayer(saxPlayerName), _, _, _) -> saxPlayerName
Making illegal states unrepresentable
From a different module ….
type Drummer = private Drummer of string
let createDrummer name =
// do some lookup to validate that this person is actually
// a drummer
let drummers = [ "Max Roache"; "Elvin Jones"; "Tony Williams" ]
if List.contains name drummers then
Some (Drummer name)
else None
// won't compile because the union case fields are not accessible
let drummer = Drummer("tom")
Making illegal states unrepresentable
Evaluate in FSI…
let drummer = createDrummer "tom"
val drummer : Drummer option = None
let drummer = createDrummer "Max Roache"
Evaluate in FSI…
val drummer : Drummer option = Some Drummer "Max Roache"
Pattern matching private data constructors
let (|Drummer|) (Drummer name) = Drummer(name)
let getBandLeader (jazzband: JazzBand) =
match jazzband with
| PianoTrio(PianoPlayer(ppn), BassPlayer(bassPlayerName), Drummer(dn)) -> ppn
| SaxTrio(SaxPlayer(spn), BassPlayer(bpn), Drummer(dn)) -> spn
| Quartet(SaxPlayer(spn), PianoPlayer(name), BassPlayer(bpn), Drummer(dn)) -> spn
Automatic currying
type Message = {
Id : Guid
Payload : string
}
let addPrefix (prefix:string, message:Message) =
{ Id = message.Id
Payload = prefix + message.Payload }
Evaluate in FSI..
val addPrefix : prefix:string * message:Message -> Message
Automatic currying
Evaluate in FSI…
let message = { Id = Guid.NewGuid(); Payload = "my payload" }
let addPrefix' prefix =
fun message ->
{ message with
Payload = prefix + message.Payload }
addPrefix’ “hello "
val it : (Message -> Message) = <fun:it@3>
let addHelloPrefix = addPrefix’ “hello "
addHelloPrefix message
Evaluate in FSI…
val it : Message = {Id = ac4ddf34-4d9d-4c16-869a-500578f33038;
Payload = “hello my payload ";}
Automatic currying
Evaluate in FSI…
val it : Message = {Id = ac4ddf34-4d9d-4c16-869a-500578f33038;
Payload = "my prefix to my payload ";}
let addHelloPrefix = addPrefix’’ “hello "
addHelloPrefix message
Evaluate in FSI…
val it : Message = {Id = ac4ddf34-4d9d-4c16-869a-500578f33038;
Payload = “hello my payload ";}
let addPrefix'' prefix message =
{ message with
Payload = prefix + message.Payload }
addPrefix'' "my prefix to " message
Functional pipelines
Evaluate in FSI…
val it : Message = {Id = ac4ddf34-4d9d-4c16-869a-500578f33038;
Payload = “header:my payload:footer ";}
let addPostfix postfix message =
{ message with
Payload = message.Payload + postfix }
//hard to read with nested parens
let transformMessage message =
(addPostfix "footer" (addPrefix'' "header:" message))
let transformMessage' message =
message
|> addPrefix'' "header:"
|> addPostfix ":footer"
transformMessage' message
Functional pipelines
Evaluate in FSI…
val it : Message = {Id = ac4ddf34-4d9d-4c16-869a-500578f33038;
Payload = “header:my payload:footer ";}
let addPostfix postfix message =
{ message with
Payload = message.Payload + postfix }
//hard to read with nested parens
let transformMessage message =
(addPostfix "footer" (addPrefix'' "header:" message))
let transformMessage' message =
message
|> addPrefix'' "header:"
|> addPostfix ":footer"
transformMessage' message
Loops to high level transformations
h u z z a h
u z z a
h u z z u h
u z z u
z z
Imperative C# implementation
static bool IsPalindrome(string candidate)
{
var endIndex = candidate.Length - 1;
for(var i = 0; i < candidate.Length/2; i++)
{
if (candidate[i] != candidate[endIndex - i])
return false;
}
return true;
}
Imperative loop in F#
let palindromeWithWhileLoop (candidate:string) =
let endIndex = candidate.Length - 1
let mutable isPalindrome = true
let mutable i = 0
while i < candidate.Length/2 && isPalindrome do
if candidate.[i] <> candidate.[endIndex - i] then
isPalindrome <- false
i <- i + 1
isPalindrome
Lets remove the mutable variables
let palindromeWithRecursiveLoop (candidate:string) =
let endIndex = candidate.Length - 1
let rec loop i isPalindrome =
if i < candidate.Length/2 && isPalindrome then
loop (i + 1) (candidate.[i] = candidate.[endIndex - i])
else
isPalindrome
loop 0 true
Simplify with pattern matching
let rec isPalindrome candidate =
let exceptLast list = (list |> List.truncate (list.Length - 1))
match candidate with
| [] -> true
| [x] -> true
| [x1; x2] -> x1 = x2
| x1 :: xs -> x1 = List.last xs && xs |> exceptLast |> isPalindrome
Removing the imperative loop
let palindromeWithTryFind (candidate: string) =
candidate
|> Seq.mapi (fun index c -> (index, c))
|> Seq.tryFind (fun (index, c) ->
let indexFromEnd = (Seq.length candidate) - (index + 1)
indexFromEnd >= index && c <> candidate.[indexFromEnd])
|> Option.isNone
Transform only the palindromes
let toUppercasePalindromes candidates =
candidates
|> Seq.filter (fun candidate -> isPalindrome candidate)
|> Seq.map (fun palindrome -> palindrome.ToUpper())
Simplified…
let toUppercasePalindromes candidates =
candidates
|> Seq.filter isPalindrome
|> Seq.map (fun palindrome -> palindrome.ToUpper())
[ "anina"; "aninaa"; "aniina"; ""; "a"; "at"; "anireina" ]
|> toUppercasePalindromes |> Seq.toList
Evaluate in FSI…
val it : string list = ["ANINA"; "ANIINA"; ""; "A"]
Learning Resources
https://fsharpforfunandprofit.com/
Kit Eason’s courses on Pluralsight
Try hackerrank problems in F#
https://www.hackerrank.com/
https://www.pluralsight.com/courses/fsharp-jumpstart

More Related Content

What's hot

Python
PythonPython
Vim Script Programming
Vim Script ProgrammingVim Script Programming
Vim Script ProgrammingLin Yo-An
 
Music as data
Music as dataMusic as data
Music as data
John Vlachoyiannis
 
Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Wen-Tien Chang
 
Go &lt;-> Ruby
Go &lt;-> RubyGo &lt;-> Ruby
Go &lt;-> Ruby
Eleanor McHugh
 
Ruby 程式語言簡介
Ruby 程式語言簡介Ruby 程式語言簡介
Ruby 程式語言簡介Wen-Tien Chang
 
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
takeoutweight
 
Alias
AliasAlias
Template Haskell Tutorial
Template Haskell TutorialTemplate Haskell Tutorial
Template Haskell Tutorialkizzx2
 
Functional pe(a)rls: Huey's zipper
Functional pe(a)rls: Huey's zipperFunctional pe(a)rls: Huey's zipper
Functional pe(a)rls: Huey's zipper
osfameron
 
Erlang Concurrency
Erlang ConcurrencyErlang Concurrency
Erlang Concurrency
Barry Ezell
 
A Taste of Python - Devdays Toronto 2009
A Taste of Python - Devdays Toronto 2009A Taste of Python - Devdays Toronto 2009
A Taste of Python - Devdays Toronto 2009
Jordan Baker
 
Poly-paradigm Java
Poly-paradigm JavaPoly-paradigm Java
Poly-paradigm Java
Pavel Tcholakov
 
2 BytesC++ course_2014_c2_ flow of control
2 BytesC++ course_2014_c2_ flow of control 2 BytesC++ course_2014_c2_ flow of control
2 BytesC++ course_2014_c2_ flow of control
kinan keshkeh
 
Google Go For Ruby Hackers
Google Go For Ruby HackersGoogle Go For Ruby Hackers
Google Go For Ruby Hackers
Eleanor McHugh
 
Vim Hacks
Vim HacksVim Hacks
Vim Hacks
Lin Yo-An
 
Declarative Thinking, Declarative Practice
Declarative Thinking, Declarative PracticeDeclarative Thinking, Declarative Practice
Declarative Thinking, Declarative Practice
Kevlin Henney
 
Free Monads Getting Started
Free Monads Getting StartedFree Monads Getting Started
Free Monads Getting Started
Kent Ohashi
 
F bound-types
F bound-typesF bound-types
F bound-types
Ikhoon Eom
 
VIM for (PHP) Programmers
VIM for (PHP) ProgrammersVIM for (PHP) Programmers
VIM for (PHP) Programmers
ZendCon
 

What's hot (20)

Python
PythonPython
Python
 
Vim Script Programming
Vim Script ProgrammingVim Script Programming
Vim Script Programming
 
Music as data
Music as dataMusic as data
Music as data
 
Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Ruby 程式語言入門導覽
Ruby 程式語言入門導覽
 
Go &lt;-> Ruby
Go &lt;-> RubyGo &lt;-> Ruby
Go &lt;-> Ruby
 
Ruby 程式語言簡介
Ruby 程式語言簡介Ruby 程式語言簡介
Ruby 程式語言簡介
 
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
 
Alias
AliasAlias
Alias
 
Template Haskell Tutorial
Template Haskell TutorialTemplate Haskell Tutorial
Template Haskell Tutorial
 
Functional pe(a)rls: Huey's zipper
Functional pe(a)rls: Huey's zipperFunctional pe(a)rls: Huey's zipper
Functional pe(a)rls: Huey's zipper
 
Erlang Concurrency
Erlang ConcurrencyErlang Concurrency
Erlang Concurrency
 
A Taste of Python - Devdays Toronto 2009
A Taste of Python - Devdays Toronto 2009A Taste of Python - Devdays Toronto 2009
A Taste of Python - Devdays Toronto 2009
 
Poly-paradigm Java
Poly-paradigm JavaPoly-paradigm Java
Poly-paradigm Java
 
2 BytesC++ course_2014_c2_ flow of control
2 BytesC++ course_2014_c2_ flow of control 2 BytesC++ course_2014_c2_ flow of control
2 BytesC++ course_2014_c2_ flow of control
 
Google Go For Ruby Hackers
Google Go For Ruby HackersGoogle Go For Ruby Hackers
Google Go For Ruby Hackers
 
Vim Hacks
Vim HacksVim Hacks
Vim Hacks
 
Declarative Thinking, Declarative Practice
Declarative Thinking, Declarative PracticeDeclarative Thinking, Declarative Practice
Declarative Thinking, Declarative Practice
 
Free Monads Getting Started
Free Monads Getting StartedFree Monads Getting Started
Free Monads Getting Started
 
F bound-types
F bound-typesF bound-types
F bound-types
 
VIM for (PHP) Programmers
VIM for (PHP) ProgrammersVIM for (PHP) Programmers
VIM for (PHP) Programmers
 

Similar to F# delight

Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my day
Tor Ivry
 
Kotlin from-scratch 2 - functions
Kotlin from-scratch 2 - functionsKotlin from-scratch 2 - functions
Kotlin from-scratch 2 - functions
Franco Lombardo
 
Functional Programming in F#
Functional Programming in F#Functional Programming in F#
Functional Programming in F#Dmitri Nesteruk
 
7 Habits For a More Functional Swift
7 Habits For a More Functional Swift7 Habits For a More Functional Swift
7 Habits For a More Functional Swift
Jason Larsen
 
Beginning Haskell, Dive In, Its Not That Scary!
Beginning Haskell, Dive In, Its Not That Scary!Beginning Haskell, Dive In, Its Not That Scary!
Beginning Haskell, Dive In, Its Not That Scary!
priort
 
Generics and Inference
Generics and InferenceGenerics and Inference
Generics and Inference
Richard Fox
 
仕事で使うF#
仕事で使うF#仕事で使うF#
仕事で使うF#bleis tift
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
Aleksandar Prokopec
 
Rustlabs Quick Start
Rustlabs Quick StartRustlabs Quick Start
Rustlabs Quick Start
sangam biradar
 
All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!
John De Goes
 
Elm: give it a try
Elm: give it a tryElm: give it a try
Elm: give it a try
Eugene Zharkov
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
Philip Schwarz
 
Unfiltered Unveiled
Unfiltered UnveiledUnfiltered Unveiled
Unfiltered Unveiled
Wilfred Springer
 
Swift - Modern & Expressive, or Magical Unicorn?
Swift  - Modern & Expressive, or Magical Unicorn?Swift  - Modern & Expressive, or Magical Unicorn?
Swift - Modern & Expressive, or Magical Unicorn?
Mike Jones
 
Think sharp, write swift
Think sharp, write swiftThink sharp, write swift
Think sharp, write swift
Pascal Batty
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kirill Rozov
 
Python Workshop - Learn Python the Hard Way
Python Workshop - Learn Python the Hard WayPython Workshop - Learn Python the Hard Way
Python Workshop - Learn Python the Hard Way
Utkarsh Sengar
 
groovy & grails - lecture 3
groovy & grails - lecture 3groovy & grails - lecture 3
groovy & grails - lecture 3
Alexandre Masselot
 
F# intro
F# introF# intro
F# intro
Alexey Raga
 

Similar to F# delight (20)

Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my day
 
Kotlin from-scratch 2 - functions
Kotlin from-scratch 2 - functionsKotlin from-scratch 2 - functions
Kotlin from-scratch 2 - functions
 
Functional Programming in F#
Functional Programming in F#Functional Programming in F#
Functional Programming in F#
 
7 Habits For a More Functional Swift
7 Habits For a More Functional Swift7 Habits For a More Functional Swift
7 Habits For a More Functional Swift
 
Beginning Haskell, Dive In, Its Not That Scary!
Beginning Haskell, Dive In, Its Not That Scary!Beginning Haskell, Dive In, Its Not That Scary!
Beginning Haskell, Dive In, Its Not That Scary!
 
Generics and Inference
Generics and InferenceGenerics and Inference
Generics and Inference
 
仕事で使うF#
仕事で使うF#仕事で使うF#
仕事で使うF#
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
Rustlabs Quick Start
Rustlabs Quick StartRustlabs Quick Start
Rustlabs Quick Start
 
All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!All Aboard The Scala-to-PureScript Express!
All Aboard The Scala-to-PureScript Express!
 
Elm: give it a try
Elm: give it a tryElm: give it a try
Elm: give it a try
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
 
Unfiltered Unveiled
Unfiltered UnveiledUnfiltered Unveiled
Unfiltered Unveiled
 
Intro toswift1
Intro toswift1Intro toswift1
Intro toswift1
 
Swift - Modern & Expressive, or Magical Unicorn?
Swift  - Modern & Expressive, or Magical Unicorn?Swift  - Modern & Expressive, or Magical Unicorn?
Swift - Modern & Expressive, or Magical Unicorn?
 
Think sharp, write swift
Think sharp, write swiftThink sharp, write swift
Think sharp, write swift
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
 
Python Workshop - Learn Python the Hard Way
Python Workshop - Learn Python the Hard WayPython Workshop - Learn Python the Hard Way
Python Workshop - Learn Python the Hard Way
 
groovy & grails - lecture 3
groovy & grails - lecture 3groovy & grails - lecture 3
groovy & grails - lecture 3
 
F# intro
F# introF# intro
F# intro
 

Recently uploaded

Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
kalichargn70th171
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Łukasz Chruściel
 
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
mz5nrf0n
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Neo4j
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Deuglo Infosystem Pvt Ltd
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
What is Augmented Reality Image Tracking
What is Augmented Reality Image TrackingWhat is Augmented Reality Image Tracking
What is Augmented Reality Image Tracking
pavan998932
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
TheSMSPoint
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
timtebeek1
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
Hornet Dynamics
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 

Recently uploaded (20)

Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
 
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
What is Augmented Reality Image Tracking
What is Augmented Reality Image TrackingWhat is Augmented Reality Image Tracking
What is Augmented Reality Image Tracking
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
E-commerce Application Development Company.pdf
E-commerce Application Development Company.pdfE-commerce Application Development Company.pdf
E-commerce Application Development Company.pdf
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 

F# delight

  • 1. August 7, 2017 Tom Prior www.prigrammer.com @priortd F# Delight
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11. Getting started – F# interactive FSI https://www.microsoft.com/net/download/core dotnet new console -lang f# -o MyConsoleApp cd MyConsoleApp dotnet restore code .
  • 12. Create fsx file and start executing code with f# interactive! Just highlight and press Alt-Enter
  • 13. The Delights • Simplicity • Immutability • Pattern matching • Encoding logic in types • Automatic currying – all functions are one arg functions • High level transformations and functional pipelines
  • 14. Immutability – let bindings let x = 2 Evaluated in FSI… val x : int = 2
  • 15. Will this increment x ?? Evaluated in FSI… val x : int = 2 val it : bool = false let x = 2 x = x + 1
  • 16. Specifying Mutability Evaluated in FSI… val mutable y : int = 3 val it : unit = () x <- x + 1 //won’t compile as x not mutable. let mutable y = 2 y <- y + 1
  • 17. Tuples let p = ("Tom", 38) fst p Evaluated in FSI …. val p : string * int = ("Tom", 38) val it : string = "Tom"
  • 18. Immutability – OO Classes type Person(name:string) = member p.Name = name
  • 19. Immutability – Records type Person = { Name : string Age : int } let p = { Name = "Tom"; Age = 56 } Evaluated in FSI… type Person = {Name: string; Age: int;} val p : Person = {Name = "Tom"; Age = 56;}
  • 20. Evaluated in FSI… val it : string = "Tom" //won't compile as records are immutable. p.Name <- "Jack" p.Name
  • 21. Immutable Collections Evaluated in FSI… val numbers : int list = [1; 2; 3; 4] open FSharp.Collections let numbers = [ 1; 2; 3; 4 ] //won't compile becuase lists are immutable numbers.[2] <- 7
  • 22. Arrays still mutable Evaluated in FSI… val names : string [] = [|"tom"; "eleanor"|] val it : string = "tom" let names = [| "tom"; "eleanor" |] names.[0] names.[0] <- "Myles" names.[0] Evaluated in FSI… val it : string = "Myles"
  • 23. Pattern matching Evaluated in FSI… val person : string * int = ("Tom", 38) val name : string = "Tom" val age : int = 38 let person = ("Tom", 38) let (name, age) = person
  • 24. Match expressions Evaluated in FSI… val getName : 'a * 'b -> 'a val person : string * int = ("Tom", 38) val it : string = "Tom" let getName person = match person with | (name, age) -> name let person = ("Tom", 38) getName person
  • 25. Pattern matching on records Evaluated in FSI… type Person = {Name: string; Age: int;} val p : Person = {Name = "Tom"; Age = 38;} val personName : string = "Tom" type Person = { Name : string; Age : int } let p = { Name = "Tom"; Age = 38 } let { Name = personName; Age = _ } = p
  • 26. Pattern matching on lists let l = [ 1; 2; 3 ] 1 2 3 [] //l can be re-written as let l = 1 :: 2 :: 3 :: []
  • 27. Evaluated in FSI… val l : int list = [1; 2; 3] val getFirst : list:'a list -> 'a val it : int = 1 let l = 1 :: 2 :: 3 :: [] let getFirst list = match list with // warning if not all patterns covered | x :: xs -> x | [] -> failwith "cannot get first on an empty list" // you wouldn't actually do this - this would return an option instead - will cover this shortly. getFirst l
  • 28. Discriminated Unions type Drummer = Drummer of string type BassPlayer = BassPlayer of string type SaxPlayer = SaxPlayer of string type PianoPlayer = PianoPlayer of string type JazzBand = | PianoTrio of PianoPlayer * BassPlayer * Drummer | SaxTrio of SaxPlayer * BassPlayer * Drummer | Quartet of SaxPlayer * PianoPlayer * BassPlayer * Drummer
  • 29. Simplified… let getBandLeader (jazzband: JazzBand) = match jazzband with | PianoTrio(PianoPlayer(ppn), BassPlayer(bassPlayerName), Drummer(dn)) -> ppn | SaxTrio(SaxPlayer(spn), BassPlayer(bpn), Drummer(dn)) -> spn | Quartet(SaxPlayer(spn), PianoPlayer(name), BassPlayer(bpn), Drummer(dn)) -> spn let getBandLeader (jazzband: JazzBand) = match jazzband with | PianoTrio(PianoPlayer(pianoPlayerName), _, _) -> pianoPlayerName | SaxTrio(SaxPlayer(saxPlayerName), _, _) -> saxPlayerName | Quartet(SaxPlayer(saxPlayerName), _, _, _) -> saxPlayerName
  • 30. Making illegal states unrepresentable From a different module …. type Drummer = private Drummer of string let createDrummer name = // do some lookup to validate that this person is actually // a drummer let drummers = [ "Max Roache"; "Elvin Jones"; "Tony Williams" ] if List.contains name drummers then Some (Drummer name) else None // won't compile because the union case fields are not accessible let drummer = Drummer("tom")
  • 31. Making illegal states unrepresentable Evaluate in FSI… let drummer = createDrummer "tom" val drummer : Drummer option = None let drummer = createDrummer "Max Roache" Evaluate in FSI… val drummer : Drummer option = Some Drummer "Max Roache"
  • 32. Pattern matching private data constructors let (|Drummer|) (Drummer name) = Drummer(name) let getBandLeader (jazzband: JazzBand) = match jazzband with | PianoTrio(PianoPlayer(ppn), BassPlayer(bassPlayerName), Drummer(dn)) -> ppn | SaxTrio(SaxPlayer(spn), BassPlayer(bpn), Drummer(dn)) -> spn | Quartet(SaxPlayer(spn), PianoPlayer(name), BassPlayer(bpn), Drummer(dn)) -> spn
  • 33. Automatic currying type Message = { Id : Guid Payload : string } let addPrefix (prefix:string, message:Message) = { Id = message.Id Payload = prefix + message.Payload } Evaluate in FSI.. val addPrefix : prefix:string * message:Message -> Message
  • 34. Automatic currying Evaluate in FSI… let message = { Id = Guid.NewGuid(); Payload = "my payload" } let addPrefix' prefix = fun message -> { message with Payload = prefix + message.Payload } addPrefix’ “hello " val it : (Message -> Message) = <fun:it@3> let addHelloPrefix = addPrefix’ “hello " addHelloPrefix message Evaluate in FSI… val it : Message = {Id = ac4ddf34-4d9d-4c16-869a-500578f33038; Payload = “hello my payload ";}
  • 35. Automatic currying Evaluate in FSI… val it : Message = {Id = ac4ddf34-4d9d-4c16-869a-500578f33038; Payload = "my prefix to my payload ";} let addHelloPrefix = addPrefix’’ “hello " addHelloPrefix message Evaluate in FSI… val it : Message = {Id = ac4ddf34-4d9d-4c16-869a-500578f33038; Payload = “hello my payload ";} let addPrefix'' prefix message = { message with Payload = prefix + message.Payload } addPrefix'' "my prefix to " message
  • 36. Functional pipelines Evaluate in FSI… val it : Message = {Id = ac4ddf34-4d9d-4c16-869a-500578f33038; Payload = “header:my payload:footer ";} let addPostfix postfix message = { message with Payload = message.Payload + postfix } //hard to read with nested parens let transformMessage message = (addPostfix "footer" (addPrefix'' "header:" message)) let transformMessage' message = message |> addPrefix'' "header:" |> addPostfix ":footer" transformMessage' message
  • 37. Functional pipelines Evaluate in FSI… val it : Message = {Id = ac4ddf34-4d9d-4c16-869a-500578f33038; Payload = “header:my payload:footer ";} let addPostfix postfix message = { message with Payload = message.Payload + postfix } //hard to read with nested parens let transformMessage message = (addPostfix "footer" (addPrefix'' "header:" message)) let transformMessage' message = message |> addPrefix'' "header:" |> addPostfix ":footer" transformMessage' message
  • 38. Loops to high level transformations h u z z a h u z z a
  • 39. h u z z u h u z z u z z
  • 40. Imperative C# implementation static bool IsPalindrome(string candidate) { var endIndex = candidate.Length - 1; for(var i = 0; i < candidate.Length/2; i++) { if (candidate[i] != candidate[endIndex - i]) return false; } return true; }
  • 41. Imperative loop in F# let palindromeWithWhileLoop (candidate:string) = let endIndex = candidate.Length - 1 let mutable isPalindrome = true let mutable i = 0 while i < candidate.Length/2 && isPalindrome do if candidate.[i] <> candidate.[endIndex - i] then isPalindrome <- false i <- i + 1 isPalindrome
  • 42. Lets remove the mutable variables let palindromeWithRecursiveLoop (candidate:string) = let endIndex = candidate.Length - 1 let rec loop i isPalindrome = if i < candidate.Length/2 && isPalindrome then loop (i + 1) (candidate.[i] = candidate.[endIndex - i]) else isPalindrome loop 0 true
  • 43. Simplify with pattern matching let rec isPalindrome candidate = let exceptLast list = (list |> List.truncate (list.Length - 1)) match candidate with | [] -> true | [x] -> true | [x1; x2] -> x1 = x2 | x1 :: xs -> x1 = List.last xs && xs |> exceptLast |> isPalindrome
  • 44. Removing the imperative loop let palindromeWithTryFind (candidate: string) = candidate |> Seq.mapi (fun index c -> (index, c)) |> Seq.tryFind (fun (index, c) -> let indexFromEnd = (Seq.length candidate) - (index + 1) indexFromEnd >= index && c <> candidate.[indexFromEnd]) |> Option.isNone
  • 45. Transform only the palindromes let toUppercasePalindromes candidates = candidates |> Seq.filter (fun candidate -> isPalindrome candidate) |> Seq.map (fun palindrome -> palindrome.ToUpper()) Simplified… let toUppercasePalindromes candidates = candidates |> Seq.filter isPalindrome |> Seq.map (fun palindrome -> palindrome.ToUpper()) [ "anina"; "aninaa"; "aniina"; ""; "a"; "at"; "anireina" ] |> toUppercasePalindromes |> Seq.toList Evaluate in FSI… val it : string list = ["ANINA"; "ANIINA"; ""; "A"]
  • 46. Learning Resources https://fsharpforfunandprofit.com/ Kit Eason’s courses on Pluralsight Try hackerrank problems in F# https://www.hackerrank.com/ https://www.pluralsight.com/courses/fsharp-jumpstart