ted.neward@newardassociates.com | Blog: http://blogs.newardassociates.com | Github: tedneward | LinkedIn: tedneward
Learn how FP is different from O-O
Learn how F# provides O-O
Get some syntax under your belt
Realize that this is just the start of a journey
dependences on mutable state
compiler out-of-order rewrites
difficulties reasoning about the code
concurrency planning/programming
functional as in mathematics' notion of function
for every x, there is a corresponding value y
this implies no side effects
not imperative statements, but expressions
x = x+1
is not increment... it's impossible
this implies expressions can be substituted
... or executed independently (parallellism)
spectrum of "functional-ness", known as purity
"pure" functional languages allow for no side effects
"impure" functional languages allow for side effects
immutable values over mutable variables
functions as first-class values
currying, partial-application of functions
expressions-not-statements
laziness/deferred execution
strongly-typed, type-inferenced
recursion
tuples, lists
pattern-matching
What is F#?
General-purpose
Object-oriented
Functional
Hybrid
Running on the .NET platform
With full Visual Studio integration
General-purpose
Meaning, use it for anything!
Games
WSDL or REST services
Web applications
Math/science calculations
Object-oriented
Object = Union of state + data
Class-based
Interfaces
Implementation inheritance
Method overriding
Functional
Functions are first-class values
Partial application
Function composition
Currying
Immutable state
Lack of side effects
Hybrid
Objects + Functions = BETTER
Use OO when it makes sense
Use FP when it makes sense
When neither makes sense, just wing it
.NET Platform
Full CLI Producer and Consumer
Runs on the CLR
Garbage-collection
Compiles to IL, JIT-optimized
Full access to the .NET platform and libraries
Full access to the .NET ecosystem (NuGet, etc)
Produce assemblies for consumption by C#/VB/etc
Visual Studio Integration
Comes out of the box in VS2010+
VS debugger, profiler, etc
Color syntax highlighting, IntelliSense, ...
F# Project types
FSI (F# Interactive)
Some example F# code
let message = "Hello, world! (From F#)" System.Console.WriteLine(message) for i = 1 to 10 do System.Console.WriteLine(message + " " + i.ToString())
Elements of note
F# is a type-inferenced language
type-qualifiers can always be appended if desired/necessary
F# has full access to the .NET platform
F# basic types are CLR basic types (mostly)
int, string, float, ... are all CLR types
Comments are (* *) pairs or // lines
/// are XML comments
Semicolon line terminators unnecessary
Whitespace-significant block structuring
Three modes of execution
compile (Visual Studio or fsc.exe)
files are compiled in order; this is important
"one-pass"/"no-lookahead" rules
script (fsi.exe)
file needs an .fsx extension in this case
REPL (Visual Studio FSI or fsi.exe)
in Visual Studio, Ctrl-Enter is your friend here
Syntax
indentation-sensitive
(* *) and // comment syntax
/// XML comments
Unicode character set
Identifiers are [a-z][A-Z][_]0-9 acceptable
let
let establishes a name/value binding
Once bound, value cannot be changed
type is often inferred
provide a type annotation to identifier when desired or necessary
let
let x = 5 let y = 4.7 let message = "Now is the time for all good men" let multilineMessage = "Now is the time for all good men to take up the cause of their country."
Types
byte, sbyte, int16, uint16, int, int32, uint, uint32, int64, uint64
float, float32, decimal
bigint (System.BigInteger)
string
char
Bounded Types
bool: true, false
unit: ()
() : unit
null is evil
Arithmetic operators
+, -, , /, %,* (exponent
Boolean operators
&& (and), || (or), not (not)
Comparison operators
<, <= less than
, >= greater than
= equality
<> inequality
Functions
Also just "let" bindings
functions aren't the same as methods
final expression provides return value
More let
let add l r = l + r let leetSpeak (phrase : string) = phrase. Replace('e', '3'). Replace('o', '0') let leet = leetSpeak "leet" // l33t let tedTest test = test "Ted" let isMe me = if me = "Ted" then "It is Ted!" else "Dunno who you are" tedTest isMe
Control flow
if/then/elif/else
for (comprehensions)
More let
let isOdd n = if (n / 2) = (n % 2) then true else false for i = 1 to 10 do System.Console.WriteLine(i) let evens n = [ for i in 0..n do if i % 2 = 0 then yield i ] let evenSingles = evens 9 // 0, 2, 4, 6, 8
Pattern matching
Control flow construct
Also a destructuring construct
Also a type matching construct
And a dessert and floor topping
Pattern matching
<</home/runner/work/Slides/Slides/Content/FSharp/basics.fs NOT FOUND>>
Lists
bracketed syntax
arrays use a different syntax, and are not preferred
cons operator (::)
range (..) generates range of values
Lists used a lot for recursive operations
Lists
let list1 = [ ] // empty list let list2 = [1; 2; 3] // list of 1, 2, 3 let list3 = 0 :: list2 // list of 0, 1, 2, 3 let range = [1 .. 100] // list of 1, 2, ..., 99, 100 // Common to use for comprehensions to build a list let evens n = [ for i in 0 .. n do if i % 2 = 0 then yield i ] let evenSingles = evens 9 // 0, 2, 4, 6, 8 // Lists have a number of functions; more on this later
Lists
let rec factorial n = if n = 0 then 1 else n * factorial (n-1) let rec sumList xs = match xs with | [] -> 0 | y::ys -> y + sumList ys
Sequences
Lazy-evaluated range of values
Similar in some ways to a list
with the exception that the sequence values aren't in memory (yet)
think IEnumerable
Lists
let allPositiveIntegers = seq { for i in 1 .. System.Int32.MaxValue do yield i } // fits in memory let alphabet = seq { for c in 'A' .. 'Z' -> c } let abc = Seq.take 3 alphabet // seq ['A';'B';'C'] // Prove it! let noisyAlphabet = seq { for c in 'A' .. 'Z' do printfn "Yielding %c" c yield c } let fifthLetter = Seq.nth 4 noisyAlphabet // 'E'
Tuples
unnamed grouping of data values
concept: DTOs are tuples
commonly used across lots of functional languages
"strucutrally-equivalent" type systems
can be "destructured" through let binding
NOTE: difference between multiple args and one tuple arg is subtle, but very real
Tuples
let speaker = ("Ted", "Neward", "iTrellis") // speaker is string * string * string let city = ("Seattle", "Washington", 5000000) // city is string * string * int let person = ("Charlotte", "Neward", 39) // person is string * string * int let firstName, lastName, age = person // firstName = "Charlotte" // lastName = "Neward" // age = 39 let add l r = l + r // add is int -> int -> int let Add (l : int, r : int) = l + r // Add is (int * int) -> int
Tuples
let people = [ ("Charlotte", "Neward", 39); ("Ted", "Neward", 42); ("Fred", "Flintstone", 51); ("Katy", "Perry", 21) ] let personsAge p ln = match p with | (_, ln, age) -> age let ages = [ for p in people do yield personsAge p "Neward" ]
Option
replacement for null
only two possible values: Some(T) or None
think of this as a "collection of 1 or 0"
but used to help isolate against no responses
TIP: where you used to use null, use an option instead
Discriminated Unions
A type that can only be one of several possible values
Each value referred to as a union case
Fully type-checked
Vaguely similar to enumerated types but with more structure
Can also include other value types as part of the value
Discriminated Unions
type Suit = | Heart | Diamond | Spade | Club type PlayingCard = | Ace of Suit | King of Suit | Queen of Suit | Jack of Suit | PointCard of int * Suit let deckOfCards = [ for suit in [Spade; Club; Heart; Diamond] do yield Ace(suit) yield King(suit) yield Queen(suit) yield Jack(suit) for value in 2 .. 10 do yield PointCard(value, suit) ]
Discriminated Unions and Pattern matching
let describeCards cards = match cards with | cards when List.length cards > 2 -> failwith "Too few cards" | [Ace(_); Ace(_)] -> "Pocket Rockets" | [King(_); King(_)] -> "Cowboys" | [PointCard(2, _); PointCard(2, _)] -> "Ducks" | [PointCard(x, _); PointCard(y, _)] when x = y -> "Pair | [first; second] -> "You got nuttin"
Modules
similar to namespaces, but permits top-level functions
more functional style
tends towards "module.function" style of invocation
Namespaces
.NET namespace, with all the same restrictions
can only contain classes, interfaces, etc
Both are "open"ed to use
Records
Sort of a "proto-object"
Named fields (unlike tuples)
Built-in behaviors (unlike objects)
Add properties, methods as desired
"Clone" records to new records
Records
open System type PersonRecord = { FirstName : string; LastName: string; Age : int} member this.FullName = FirstName + " " + LastName member this.Greet(other : string) = String.Format("{0} greets {1}", this.FirstName, other) let ted = { FirstName = "Ted"; LastName = "Neward"; Age = 42 } Console.WriteLine("{0} {1} is {2}", ted.FirstName, ted.LastName, ted.Age) // Cloning records: use 'with' let michael = { ted with FirstName="Michael"; Age=20 }
Classes
Constructors
"primary" constructor appears on type declaration
"secondary" constructors defer to primary
Fields
fields are implied from constructor parameters
can also be explicitly declared if desired, but...
implicitly private, implicitly in scope, implicitly immutable
Classes: constructors, fields
type Person(firstName : string, lastName : string, age : int) = member p.FirstName = firstName member p.LastName = lastName member p.Age = age
Classes
Properties
Properties are members (use the keyword)
Properties are declared using "self" syntax
Properties are implicitly read-only
Methods
Methods are members (use the keyword)
Methods accept a body
Method return is the final expression in the body
Classes: methods
// from before ... member p.Work() = System.Console.WriteLine(firstName + " is hard at work.") member p.Play(activity) = System.Console.WriteLine(firstName + " loves " + activity)
Classes
Methods can accept optional parameters
optional params prefixed with "?"
optional params are typed as Option
Methods can accept named parameters
Classes: methods
member p.Drink(?kind : string, ?amount : int) = let bK = match kind with None -> "IPA" | Some b -> b let bA = match amount with None -> 1 | Some amt -> amt System.Console.WriteLine("I'm drinking {0} {1}s!", bA, bK) let p = Person("Ted", "Neward", 42) p.Drink("Macallan", 1) p.Drink(amount=2, kind="Zinfandel")
Inheritance (implementation)
Types can describe IS-A relationships using "inherit"
call base constructor in "inherit" syntax
classes implicitly inherit System.Object
Use override (instead of member) for overriding base
Classes: inheritance
type Student(fN:string, lN:string, a:int, subject:string) = inherit Person(fN, lN, a) member st.Subject = subject override st.ToString() = System.String.Format("[Student: subject = {0}, " + base.ToString() + "]", subject) let s = Student("Michael", "Neward", 20, "Video Game Design") s.Drink()
Inheritance (interfaces)
Interfaces are just types without implementation
Or use more explicit "interface ... end" idiom
Either way, it's a .NET interface
Implement "interface with"
These are all "explicit interface" implementations
this means you need an explicit downcast (":>") to call
Classes: interfaces
type IStudy = abstract Study : string -> unit type IAlsoStudy = interface abstract member Study : string -> unit end type Programmer(fN:string,lN:string,a:int) = inherit Person(fN,lN,a) interface IStudy with member this.Study (subject:string) : unit = printfn "Now I know %s !" subject let db = Programmer("Don", "Box", 54) let dbs = db :> IStudy dbs.Study("Kung Fu")
Object Expressions
Sometimes we want a one-off implementation of an interface
This is an "object expression", and is "new interface with"
Classes: object expressions
let monkey = { new IStudy with member m.Study(subject:string) = System.Console.WriteLine("Ook eek aah aah {0}", subject) } monkey.Study("Visual Basic")
There's a lot of power buried inside this beast
Spend the time to experiment
Don't try to do everything as O-O; embrace the FP
Spend serious time exploring pattern-matching
Don't freak out over immutable values
Embrace function composition; not everything has to be an object
Books
Professional F# 2.0
by Neward, Minerich, Erickson, Crowell (Wrox)
Expert F# 3.0
by Syme (APress)
Programming F# 3.0
by Smith (OReilly)
Web
Try F#: F# in your browser
http://www.tryfsharp.org (equires Silverlight plugin)
F# Foundation
http://fsharp.org/
MSDN and MSDN Magazine
Architect, Engineering Manager/Leader, "force multiplier"
http://www.newardassociates.com
http://blogs.newardassociates.com
Sr Distinguished Engineer, Capital One
Educative (http://educative.io) Author
Performance Management for Engineering Managers
Books
Developer Relations Activity Patterns (w/Woodruff, et al; APress, forthcoming)
Professional F# 2.0 (w/Erickson, et al; Wrox, 2010)
Effective Enterprise Java (Addison-Wesley, 2004)
SSCLI Essentials (w/Stutz, et al; OReilly, 2003)
Server-Based Java Programming (Manning, 2000)