4. SYNTAX
int euler1(int max) {
var total = 0;
for(var n=1; n<max; n++) {
if(n % 3 == 0 || n % 5 == 0){
total += n;
}
}
return total;
}
euler1(1000);
C#
let euler1 max =
[1..max-1]
|> List.filter (fun n -> n % 3 = 0 || n % 5 = 0)
|> List.sum
euler1 1000
F#
5. SYNTAX – VS LINQ
int euler1(int max) {
return Enumerable.Range(1, max - 1)
.Where(n => n % 3 == 0 || n % 5 == 0)
.Sum();
}
euler1(1000);
C#
let euler1 max =
[1..max-1]
|> List.filter (fun n -> n % 3 = 0 || n % 5 = 0)
|> List.sum
euler1 1000
F#
6. TYPE INFERENCE
int x = 3;
long y = 4;
var z = x + y; // = 7
C# let x = 3
let y:int64 = 4L
x + y
F#
The type 'int64' does not
match the type 'int'
7. AUTOMATIC GENERALIZATION
val firstInGroup :
g:('a -> 'b) -> list:seq<'a> -> seq<'b * 'a> when 'b : equality
public IEnumerable<Tuple<U,T>> firstInGroup<T,U>
(Func<T,U> g, IEnumerable<T> list) {
return list.GroupBy(g)
.Select(grp => new Tuple<U, T>(grp.Key, grp.First()));
}
C#
let firstInGroup g list =
list
|> Seq.groupBy g
|> Seq.map (fun (key,items) -> key, Seq.head items)
F#
8. GENERALIZE THIS!
int add<T>(T x, T y) where T: op_addition {
return x + y;
}
C#
let add x y = x + y
add 3 4
add 4.2 5.1
F# let inline add x y = x + y
add 3 4
add 4.2 5.1
add "hello" "World"
F#
9. IMMUTABILITY
Eliminate unintended side effects
Sets you up for multi-core programming
Debugging is easier
Testability is higher
Intended side effects are necessary
Performance
10. IMMUTABILITY - EXAMPLE
Example from “Inside F#” blog
let actions = List.init 5 (fun i -> fun() -> i*2)
for act in actions do
printf "%d " (act())
F#
List<Func<int>> actions = new List<Func<int>>();
for (int i = 0; i < 5; ++i) {
actions.Add( () => i * 2 );
}
foreach (var act in actions) {
Console.WriteLine( act() );
}
C#
The mutable variable 'i' is used in an invalid way.
Mutable variables cannot be captured by closures.
Consider eliminating this use of mutation or using a
heap-allocated mutable reference cell via 'ref' and '!'.
12. FUNCTIONS AND FUNCTIONAL TYPES
Which problem would you rather focus on?
a) Where the code should live
b) What the code should do
13. COMPOSITION VS INHERITANCE
Is-a relationship that extends the base class
Very high coupling
Subclasses may not need all functionality from base class
Subclass has to be aware of the base class’s implementation
Ninject StructureMap
Castle WindsorUnity
Interface-dependent
14. FUNCTION COMPOSITION
Pipeline Operator: |>
Return value of first function becomes the last parameter of second function
Forward Composition Operator: >>
Create new functions that are sequences of existing functions
webUrl
|> downloadPage |> extractMetaInfo |> categorizeResource
F#
let categorizeUrl =
downloadPage >> extractMetaInfo >> categorizeResource
let categorizeEmail =
parseEmail >> extractDetail >> categorizeResource
categorizeUrl webUrl
categorizeEmail email
F#
15. FUNCTION COMPOSITION
Partial Application
Create new functions by supplying some of the arguments to an existing function
let MSBuild properties (outputPath:string) (targets:string) =
//Do some msbuild stuff
let MSBuildDebug = MSBuild ["Configuration","Debug"]
let MSBuildRelease = MSBuild ["Configuration","Release"]
F#
* From FAKE
16. PATTERN MATCHING
let data = ("Cleveland", 390000)
let city, population = data
F#
let x = 9
match x with
| num when num < 10 -> printfn "Less than ten"
| _ -> printfn "Greater than or equal to ten"
F#
17. DISCRIMINATED UNIONS
type Shape =
| Square of int
| Rectangle of float*float
| Circle of float
F#
let getArea shape =
match shape with
| Square side -> float(side * side)
| Rectangle(w,h) -> w * h
| Circle r -> System.Math.PI * r * r
F#
let sq = Square 7
let rect = Rectangle 2.2 3.3
let cir = Circle 3.4
F#
19. OBJECT MODELING
* From F# Deep Dives
type MarkdownDocument = list<MarkdownBlock>
and MarkdownBlock =
| Heading of int * MarkdownSpans
| Paragraph of MarkdownSpans
| CodeBlock of list<string>
and MarkdownSpans = list<MarkdownSpan>
and MarkdownSpan =
| Literal of string
| InlineCode of string
| Strong of MarkdownSpans
| Emphasis of MarkdownSpans
| Hyperlink of MarkdownSpans * string
F#
22. UNITS OF MEASURE
unitsOfMeasure.fsx(11,19): error FS0001: Type mismatch. Expecting a
int<mi> []
but given a
int<km> []
The unit of measure 'mi' does not match the unit of measure 'km'
[<Measure>]
type mi
[<Measure>]
type km
// define some values
let mike = [| 6<mi>; 9<mi>; 5<mi>; 18<mi> |]
let chris = [| 3<km>; 5<km>; 2<km>; 8<km> |]
let totalDistance = (Array.append mike chris) |> Array.sum
F#
23. UNITS OF MEASURE
enum DistanceUnit {
Miles,
Kilometers
}
class Run {
private float distance;
private DistanceUnit unit;
public Run(float distance, DistanceUnit unit){
this.distance = distance;
this.unit = unit;
}
}
C#
24. EXHAUSTIVE PATTERN MATCHING
//Model
module Person =
type T = Person of string
let create name =
if String.IsNullOrWhiteSpace(name) then None
else Some(Person name)
let value (Person p) = p
//DAL
let save person =
//put the person in the database…
Some 42
//UI
let readInput name =
match Person.create name with
| None -> printfn "Please supply a name"
| Some p ->
match save p with
| None -> printfn "An error occurred"
| Some id -> printfn "The id for %s is %d" (Person.value p) id
F#
25. EXHAUSTIVE PATTERN MATCHING
//DAL
type DatabaseResult<'a> =
| Success of 'a
| UniqueViolation
| GeneralException of Exception
//UI
let readInput name =
match Person.create name with
| None -> printfn "Please supply a name"
| Some p ->
match save p with
| Success(id) ->
printfn "The id for %s is %d" (Person.value p) id
| UniqueViolation ->
printfn "The name %s already exists" (Person.value p)
| GeneralException(ex) ->
printfn "%s" ex.Message
F#
F# language make code easier to understandCan you use F# for a wide range of problems
Small teams, close to businessCut teeth on XPPFP
Who has written any F#?Who gets paid to write F#?A lot like most of you: not an expert.Wanted to stretch my brain like what I see so far I want to share
{} () ; returnNot completely noise…Compiler needs curly bracesIndentingLINQ: adds a lot to readability, but uses:higher order functionsChaining – tied to an interface
Let’s talk about types
- Code reuse! You don’t see the constraints, you see the concepts – the behavior.
"inline“- gives per-type versions of the function, big performance gain over generics- Needed for code that uses overloaded operators – they statically resolve to the default (usually int)
Makes your code more predictableThe default is immutability“minimization” not “elimination”Immutable objects are thread safe
10 10 10 10 100 2 4 6 8
SyntaxGeneralizationImmutability
F# is a hybridThesethings are not available in the C# language
Composition: pass dependencies at runtime into an instance. Operations are interface-dependentLook back at LINQ exampleTalk about “function composition” in F#...
PipelineDefine a sequence of operationsAny function can be a part of the pipeline – not limited to a particular interfaceForward composition
Great in libraries to create functions that take defaultsOr for eliminating boolean parameters, making existing libraries easier to work with
Decompose or extract specific infoCompare data with a structurelet binding AND program control
“Object reference not set to an instance of an object.”Very important – eliminatesNullReferenceExceptionsWith pattern matching, forces client code to check for None
Simple to understandInstead of strings named “Literal”, “Literal” is a type
Model: use functional types to concisely represent complex object models (especially hierarchies)Flow: most appsTake data inDo some workShow results of workBecause immutable, your thinking changes from “mutate the object” to represent the results to “transform” some data
Compilers are nice because they tell us when we do something bad.What if the compiler was more proactive (like in the immutability example)?
Annotate values in your code with units
Just a structure. Not even values…. “new” up a bunch, etc.Think of the work to get the compiler to tell you when you attempt to add miles and kilometers!point: I’m sure it’s possible. But it won’t be nearly as concise or readable.
You have to deal with return values.
Patterns are exhaustiveNot only detects missingImpossibleRedundant
Have to know what the state of the model is compared to the state of the database
UOM: always compare apples to applesPM: compiler checks for edge cases; forces you to dealTP: don’t worry about state of two disconnected things
Same input, same output; test in isolationCreate functions that solve small problems in your domain (Lego™ blocks), then combine themCreate types that enforce correctness, and force clients to follow the rules
Don’t ignore other functional languages – like OO, there’s a lot to learn from other languagescaml or lisp basedThink polyglot – use functional where you think you can.