Reasonable Code With Fsharp


Published on

Published in: Technology
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • 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.
  • Reasonable Code With Fsharp

    1. 1. embrace the paradigmREASONABLE CODE WITH F#
    2. 2. ABOUT ME
    3. 3. SECTION: OVERVIEWHelp the human
    4. 4. 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.sumeuler1 1000F#
    5. 5. SYNTAX – VS LINQint 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.sumeuler1 1000F#
    6. 6. TYPE INFERENCEint x = 3;long y = 4;var z = x + y; // = 7C# let x = 3let y:int64 = 4Lx + yF#The type int64 does notmatch the type int
    7. 7. AUTOMATIC GENERALIZATIONval firstInGroup :g:(a -> b) -> list:seq<a> -> seq<b * a> when b : equalitypublic 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|> (fun (key,items) -> key, Seq.head items)F#
    8. 8. GENERALIZE THIS!int add<T>(T x, T y) where T: op_addition {return x + y;}C#let add x y = x + yadd 3 4add 4.2 5.1F# let inline add x y = x + yadd 3 4add 4.2 5.1add "hello" "World"F#
    9. 9. IMMUTABILITYEliminate unintended side effectsSets you up for multi-core programmingDebugging is easierTestability is higherIntended side effects are necessaryPerformance
    10. 10. IMMUTABILITY - EXAMPLEExample from “Inside F#” bloglet actions = List.init 5 (fun i -> fun() -> i*2)for act in actions doprintf "%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 aheap-allocated mutable reference cell via ref and !.
    11. 11. OVERVIEW1.Human readable2.Reusability3.Sensible defaults
    12. 12. FUNCTIONS AND FUNCTIONAL TYPESWhich problem would you rather focus on?a) Where the code should liveb) What the code should do
    13. 13. COMPOSITION VS INHERITANCEIs-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 implementationNinject StructureMapCastle WindsorUnityInterface-dependent
    14. 14. FUNCTION COMPOSITIONPipeline Operator: |>Return value of first function becomes the last parameter of second functionForward Composition Operator: >>Create new functions that are sequences of existing functionswebUrl|> downloadPage |> extractMetaInfo |> categorizeResourceF#let categorizeUrl =downloadPage >> extractMetaInfo >> categorizeResourcelet categorizeEmail =parseEmail >> extractDetail >> categorizeResourcecategorizeUrl webUrlcategorizeEmail emailF#
    15. 15. FUNCTION COMPOSITIONPartial ApplicationCreate new functions by supplying some of the arguments to an existing functionlet MSBuild properties (outputPath:string) (targets:string) =//Do some msbuild stufflet MSBuildDebug = MSBuild ["Configuration","Debug"]let MSBuildRelease = MSBuild ["Configuration","Release"]F#* From FAKE
    16. 16. PATTERN MATCHINGlet data = ("Cleveland", 390000)let city, population = dataF#let x = 9match x with| num when num < 10 -> printfn "Less than ten"| _ -> printfn "Greater than or equal to ten"F#
    17. 17. DISCRIMINATED UNIONStype Shape =| Square of int| Rectangle of float*float| Circle of floatF#let getArea shape =match shape with| Square side -> float(side * side)| Rectangle(w,h) -> w * h| Circle r -> System.Math.PI * r * rF#let sq = Square 7let rect = Rectangle 2.2 3.3let cir = Circle 3.4F#
    18. 18. OPTION TYPEtype Option<‘T> =| None| Some of ‘TF#
    19. 19. OBJECT MODELING* From F# Deep Divestype 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 * stringF#
    20. 20. FUNCTIONS AND FUNCTIONAL TYPES1.Think small, build big2.Model3.Flow
    21. 21. COMPILER CHECKED CORRECTNESSStep 1: Create typesStep 2: Lean on the compiler
    22. 22. UNITS OF MEASUREunitsOfMeasure.fsx(11,19): error FS0001: Type mismatch. Expecting aint<mi> []but given aint<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.sumF#
    23. 23. UNITS OF MEASUREenum 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. 24. EXHAUSTIVE PATTERN MATCHING//Modelmodule Person =type T = Person of stringlet create name =if String.IsNullOrWhiteSpace(name) then Noneelse 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) idF#
    25. 25. 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.MessageF#
    26. 26. DATABASE ACCESS, TOO?Amount of code added to project
    27. 27. COMPILER CHECKED CORRECTNESS1.Focus on the problem2.Don’t forget stuff
    28. 28. SUMMARYTo Reason: To make sense ofSyntax & IdiomsFunctional compositionCompiler-checked correctness
    29. 29. NOW WHAT?