reasonable code with fsharp
DESCRIPTION
TRANSCRIPT
![Page 1: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/1.jpg)
embrace the paradigm
REASONABLE CODE WITH F#
![Page 3: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/3.jpg)
SECTION: OVERVIEWHelp the human
![Page 4: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/4.jpg)
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#
![Page 5: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/5.jpg)
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#
![Page 6: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/6.jpg)
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'
![Page 7: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/7.jpg)
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#
![Page 8: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/8.jpg)
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#
![Page 9: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/9.jpg)
IMMUTABILITY
BENEFITS
DRAWBACKS
Eliminate unintended side effectsSets you up for multi-core programmingDebugging is easierTestability is higher
Intended side effects are necessaryPerformance
![Page 10: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/10.jpg)
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 '!'.
![Page 11: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/11.jpg)
OVERVIEW
1.Human readable2.Reusability3.Sensible defaults
![Page 12: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/12.jpg)
FUNCTIONS AND FUNCTIONAL TYPES
Which problem would you rather focus on?
a) Where the code should live
b) What the code should do
![Page 13: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/13.jpg)
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
![Page 14: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/14.jpg)
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#
![Page 15: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/15.jpg)
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
![Page 16: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/16.jpg)
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
![Page 17: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/17.jpg)
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#
![Page 18: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/18.jpg)
OPTION TYPE
type Option<‘T> = | None | Some of ‘T
F#
![Page 19: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/19.jpg)
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#
![Page 20: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/20.jpg)
FUNCTIONS AND FUNCTIONAL TYPES
1.Think small, build big2.Model3.Flow
![Page 21: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/21.jpg)
COMPILER CHECKED CORRECTNESS
Step 1: Create types
Step 2: Lean on the compiler
![Page 22: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/22.jpg)
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#
![Page 23: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/23.jpg)
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#
![Page 24: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/24.jpg)
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#
![Page 25: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/25.jpg)
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#
![Page 26: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/26.jpg)
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
![Page 27: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/27.jpg)
COMPILER CHECKED CORRECTNESS
1.Focus on the problem2.Don’t forget stuff
![Page 28: Reasonable Code With Fsharp](https://reader033.vdocuments.us/reader033/viewer/2022061210/54907a0fb47959a4028b4a18/html5/thumbnails/28.jpg)
SUMMARY
To Reason: To make sense of
Syntax & IdiomsFunctional compositionCompiler-checked correctness