Post on 17-Dec-2014
description
embrace the paradigm
REASONABLE CODE WITH F#
ABOUT ME
@mfalanga
me@michaelfalanga.com
SECTION: OVERVIEWHelp the human
SYNTAXint 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#
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#
TYPE INFERENCE
STRONGSTATIC
int x = 3;long y = 4;
var z = x + y; // = 7
C# let x = 3let y:int64 = 4L
x + y
F#
The type 'int64' does not match the type 'int'
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#
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 4add 4.2 5.1
F# let inline add x y = x + y
add 3 4add 4.2 5.1add "hello" "World"
F#
IMMUTABILITY
BENEFITS
DRAWBACKS
Eliminate unintended side effectsSets you up for multi-core programmingDebugging is easierTestability is higher
Intended side effects are necessaryPerformance
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 '!'.
OVERVIEW
1.Human readable2.Reusability3.Sensible defaults
FUNCTIONS AND FUNCTIONAL TYPES
Which problem would you rather focus on?
a) Where the code should live
b) What the code should do
COMPOSITION VS INHERITANCE
Is-a relationship that extends the base classVery high couplingSubclasses may not need all functionality from base classSubclass has to be aware of the base class’s implementation
Inheritance
Composition
Ninject StructureMap
Castle WindsorUnityInterface-dependent
FUNCTION COMPOSITIONPipeline 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 webUrlcategorizeEmail email
F#
FUNCTION COMPOSITION
Partial ApplicationCreate 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
PATTERN MATCHING
let data = ("Cleveland", 390000)let city, population = data
F#
let x = 9match x with | num when num < 10 -> printfn "Less than ten" | _ -> printfn "Greater than or equal to ten"
F#
DECOMPOSE
COMPARE
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 7let rect = Rectangle 2.2 3.3let cir = Circle 3.4
F#
OPTION TYPE
type Option<‘T> = | None | Some of ‘T
F#
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#
FUNCTIONS AND FUNCTIONAL TYPES
1.Think small, build big2.Model3.Flow
COMPILER CHECKED CORRECTNESS
Step 1: Create types
Step 2: Lean on the compiler
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 valueslet 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#
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#
EXHAUSTIVE PATTERN MATCHING//Modelmodule Person = type T = Person of string
let create name = if String.IsNullOrWhiteSpace(name) then None else Some(Person name)
let value (Person p) = p
//DALlet save person = //put the person in the database… Some 42
//UIlet 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#
EXHAUSTIVE PATTERN MATCHING//DALtype DatabaseResult<'a> = | Success of 'a | UniqueViolation | GeneralException of Exception
//UIlet 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#
DATABASE ACCESS, TOO?
1. Reference type provider
2. Provide type provider connection
3. GO!
1. Add EF template
2. Give details about connection
3. Decide what to import
4. Wait for files to be generated
5. GO!
Entity FrameworkType Provider
Amount of code added to project
COMPILER CHECKED CORRECTNESS
1.Focus on the problem2.Don’t forget stuff
SUMMARY
To Reason: To make sense of
Syntax & IdiomsFunctional compositionCompiler-checked correctness