SlideShare ist ein Scribd-Unternehmen logo
1 von 46
Downloaden Sie, um offline zu lesen
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

Weitere ähnliche Inhalte

Was ist angesagt?

Vim Script Programming
Vim Script ProgrammingVim Script Programming
Vim Script ProgrammingLin Yo-An
 
Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Ruby 程式語言入門導覽
Ruby 程式語言入門導覽Wen-Tien Chang
 
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
 
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 zipperosfameron
 
Erlang Concurrency
Erlang ConcurrencyErlang Concurrency
Erlang ConcurrencyBarry 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 2009Jordan Baker
 
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 HackersEleanor McHugh
 
Declarative Thinking, Declarative Practice
Declarative Thinking, Declarative PracticeDeclarative Thinking, Declarative Practice
Declarative Thinking, Declarative PracticeKevlin Henney
 
Free Monads Getting Started
Free Monads Getting StartedFree Monads Getting Started
Free Monads Getting StartedKent Ohashi
 
VIM for (PHP) Programmers
VIM for (PHP) ProgrammersVIM for (PHP) Programmers
VIM for (PHP) ProgrammersZendCon
 

Was ist angesagt? (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
 

Ähnlich wie F# Delight - Getting Started with F# Interactive and Functional Programming Concepts

Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my dayTor Ivry
 
Kotlin from-scratch 2 - functions
Kotlin from-scratch 2 - functionsKotlin from-scratch 2 - functions
Kotlin from-scratch 2 - functionsFranco 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 SwiftJason 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 InferenceRichard Fox
 
仕事で使うF#
仕事で使うF#仕事で使うF#
仕事で使うF#bleis tift
 
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
 
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 CatsPhilip Schwarz
 
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 swiftPascal 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 3Kirill 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 WayUtkarsh Sengar
 

Ähnlich wie F# Delight - Getting Started with F# Interactive and Functional Programming Concepts (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
 

Kürzlich hochgeladen

SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogueitservices996
 
Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonLeveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonApplitools
 
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxReal-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxRTS corp
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfRTS corp
 
eSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolseSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolsosttopstonverter
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics
 
VictoriaMetrics Anomaly Detection Updates: Q1 2024
VictoriaMetrics Anomaly Detection Updates: Q1 2024VictoriaMetrics Anomaly Detection Updates: Q1 2024
VictoriaMetrics Anomaly Detection Updates: Q1 2024VictoriaMetrics
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Rob Geurden
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...OnePlan Solutions
 
SoftTeco - Software Development Company Profile
SoftTeco - Software Development Company ProfileSoftTeco - Software Development Company Profile
SoftTeco - Software Development Company Profileakrivarotava
 
Understanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM ArchitectureUnderstanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM Architecturerahul_net
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?Alexandre Beguel
 
2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shardsChristopher Curtin
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsSafe Software
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsChristian Birchler
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Developmentvyaparkranti
 
Salesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZSalesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZABSYZ Inc
 

Kürzlich hochgeladen (20)

SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogue
 
Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonLeveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
 
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxReal-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
 
eSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolseSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration tools
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
 
VictoriaMetrics Anomaly Detection Updates: Q1 2024
VictoriaMetrics Anomaly Detection Updates: Q1 2024VictoriaMetrics Anomaly Detection Updates: Q1 2024
VictoriaMetrics Anomaly Detection Updates: Q1 2024
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
 
SoftTeco - Software Development Company Profile
SoftTeco - Software Development Company ProfileSoftTeco - Software Development Company Profile
SoftTeco - Software Development Company Profile
 
Understanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM ArchitectureUnderstanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM Architecture
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?
 
2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards2024 DevNexus Patterns for Resiliency: Shuffle shards
2024 DevNexus Patterns for Resiliency: Shuffle shards
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data Streams
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
 
VK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web DevelopmentVK Business Profile - provides IT solutions and Web Development
VK Business Profile - provides IT solutions and Web Development
 
Salesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZSalesforce Implementation Services PPT By ABSYZ
Salesforce Implementation Services PPT By ABSYZ
 

F# Delight - Getting Started with F# Interactive and Functional Programming Concepts

  • 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