Your SlideShare is downloading. ×
0
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
F# Intro for Scala Developers
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

F# Intro for Scala Developers

5,464

Published on

Presentation 4/11/2011 at Boston Area Scala Enthusiasts, MS NERD Center, Cambridge, MA.

Presentation 4/11/2011 at Boston Area Scala Enthusiasts, MS NERD Center, Cambridge, MA.

Published in: Technology
1 Comment
3 Likes
Statistics
Notes
  • Slides 11-20 have an 'Oops! This slide did not convert properly hence cannot be displayed'
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
5,464
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
36
Comments
1
Likes
3
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Boston Area Scala Enthusiasts, April 11 th , 2011 • Microsoft NERD • Cambridge, MA let talk = things |> Seq.filter (fsharp >> cool) |> Seq.map scala |> Seq.take n
  • 2. <ul><li>F# and Scala are two relatively recent hybrid object-oriented/functional languages that target two of the most widespread platforms in the world today (.NET and Java/JVM). In a sense they are two unique approaches to solving similar problems. </li></ul><ul><li>We’ll look at </li></ul><ul><ul><li>Points of Intersection </li></ul></ul><ul><ul><li>Points of Difference </li></ul></ul><ul><ul><li>Points of View </li></ul></ul>
  • 3. <ul><li>Hybrid OO/Functional approach </li></ul><ul><li>Pragmatic approach </li></ul><ul><li>Seamless integration with rich existing ecosystems (.NET, JVM) </li></ul><ul><li>More or less based on previous languages (F# :: Ocaml, Scala :: Java, other influences such as Python, Ruby) </li></ul><ul><li>Listed below are 30+ features they have in common </li></ul><ul><li>&quot;A Language that Grows on You&quot; – both very extensible, many core features are in fact not built-in to the language </li></ul>
  • 4. <ul><li>Important differences in approach, syntax, features </li></ul><ul><li>Very distinct personalities to both languages </li></ul>
  • 5. <ul><li>Emerging out of rich traditions </li></ul><ul><li>Elegant approaches to modern problems </li></ul>
  • 6. <ul><li>Beginnings in C/C++. Hints of functional in the STL, OO patterns </li></ul><ul><li>Java arrives on scene – so much less painful than C++: garbage collection, half the lines of code, etc. </li></ul><ul><li>C# – exciting new Java-like language but better for writing Windows-based applications </li></ul><ul><li>C# 3.0 and LINQ – lots of functional constructs (delegates, closures, lambdas, LINQ) </li></ul><ul><li>Looking for something with the fun and expressiveness of languages like Python and Ruby, a “full” language that could double as a scripting language, and with the power (and familiarity) of static typing, less emphasis on OO, and support for .NET and the .NET ecosystem (ASP.NET MVC for example) – and discovered F# </li></ul><ul><li>Java the language (NOT the ecosystem) has stagnated – Scala offers an exciting way forward </li></ul>
  • 7. <ul><li>Statically typed, strongly typed </li></ul><ul><li>Type inference </li></ul><ul><li>Succinct, elegant syntax </li></ul><ul><li>Combination of those 3 make both F# and Scala “feel” like dynamic languages (e.g. Python, Ruby), but have full benefit of static typing </li></ul><ul><li>Mixed/hybrid paradigm: OO and Functional </li></ul><ul><li>Target major platforms, leverage existing ecosystems: F#: .NET CLR/Mono, use C# libraries; Scala: JVM and some .NET, use Java libraries </li></ul><ul><li>Generics </li></ul><ul><li>Operators </li></ul><ul><li>Pattern Matching </li></ul><ul><li>Immutability </li></ul><ul><li>Recursion </li></ul><ul><li>Tail-call optimization </li></ul>
  • 8. <ul><li>Option, Some and None </li></ul><ul><li>Classes, interfaces, abstract classes, try/catch/finally/exceptions </li></ul><ul><li>lazy support, infinite sequences </li></ul><ul><li>Constructors where parameters become auto-generated fields/properties </li></ul><ul><li>Array/list/sequence comprehensions, yield </li></ul><ul><li>Functional data structures: Lists, Maps </li></ul><ul><li>Tuples </li></ul><ul><li>Lambda functions, higher order functions </li></ul><ul><li>Virtual and overridden methods </li></ul><ul><li>Closures </li></ul><ul><li>Map, filter, fold, reduce and friends </li></ul><ul><li>Partial function application/currying </li></ul><ul><li>Reflection – uses underlying .NET or Java reflection plus add unique features </li></ul><ul><li>Point-free style </li></ul><ul><li>Annotations/metadata – use underlying .NET and Java support </li></ul><ul><li>REPL </li></ul><ul><li>Auto-documentation </li></ul><ul><li>DSLs </li></ul>
  • 9. <ul><li>Don Syme, primary creator of F#, was main force behind .NET generics. Anders Hejlsberg, lead architect of C#, was lead architect of Pascal. </li></ul><ul><li>Martin Odersky, creator of Scala, main force behind generics in Java. Martin spent grad years working in group led by Niklaus Wirth who developed Pascal </li></ul>
  • 10. <ul><li>Type inference differences – F# uses Hindley/Milner (which looks at entire function) and tends to need less type annotation (plus Scala has more complex type system, variance which H/M has trouble with). However, F# sometimes needs explicit casting in cases where Scala would not (int -> double, interfaces must be explicit, etc.). </li></ul><ul><li>Syntax differences: F# is whitespace significant </li></ul><ul><li>Scala has more sophisticated/complex type system: traits, variance, higher kinded </li></ul><ul><li>F# supports static methods but not explicit singletons (like Scala object) </li></ul><ul><li>Scala embedded XML – though F# can use DSL or leverage XLINQ </li></ul><ul><li>Visibility – F# has no protected, only internal; Scala has more options </li></ul><ul><li>F# philosophy is to de-emphasize OO, object hierarchies while still supporting it (plus interoperability with .NET). Scala embraces OO wholeheartedly and expands it </li></ul><ul><li>F# function composition, etc. </li></ul>
  • 11. <ul><li>F# Pipelining, function composition vs. Fluent Interface </li></ul><ul><li>F# Discriminated Unions (difference?) vs. Scala case classes </li></ul><ul><li>F# Mailbox Processor vs. Scala Actors </li></ul><ul><li>F# Modules vs. Scala import and Predef – ability to have short functions in code with qualifying them as in C#/Java static methods </li></ul><ul><li>DSL support </li></ul><ul><li>F# WebSharper vs. Scala Lift: DSL/Functional based dynamic web application platforms, generate JavaScript </li></ul><ul><li>F# Object Expressions </li></ul><ul><li>Scala traits/mixins </li></ul><ul><li>F# Active Patterns </li></ul><ul><li>F# Units of Measure </li></ul><ul><li>F# Workflows / Computational Expressions (Monads) </li></ul><ul><li>F# async workflows </li></ul><ul><li>F# Reactive Extensions </li></ul>
  • 12. <ul><li>F# values are immutable by default, you have to add mutable if desired </li></ul><ul><li>“ let” binding is immutable, similar to Scala “val” </li></ul><ul><li>“ let mutable” binding is mutable, similar to Scala “var” </li></ul><ul><li>Use <- operator instead of = for assignment </li></ul>// F# let a = 42 let mutable m = 100 a <- 10 // won't compile m <- 101 // OK a = 100 // OK, but it's a boolean expression! // Scala val a = 42 var m = 100
  • 13. <ul><li>Statically typed – all the benefits of static typing </li></ul><ul><li>However, lightweight syntax and type inference make them &quot;feel&quot; in practice much closer to dynamically typed languages like Python, Ruby, JavaScript </li></ul><ul><li>F# actually even more strongly typed than C# - for example explicit conversions needed (int -> float, object -> interface) </li></ul><ul><li>However Hindley-Milner type inference makes F# extremely succinct, often very few type annotations needed </li></ul>
  • 14. <ul><li>C# 2.0 is about where Java 6 is – have to explicitly declare everything </li></ul><ul><li>C# 3.0 made significant advances with “var” keyword, in many simple cases as succinct as F# - however C# can only do this for local variables, not class members, etc. </li></ul>Dictionary<string,int> dict = new Dictionary<string,int>(); C# 2.0/Java 6 var dict = new Dictionary<string,int>(); C# 3.0 let dict = Dictionary<string,int>() F#
  • 15. <ul><li>C# 3.0 has lambda expressions – but need to be explicit about types </li></ul><ul><li>C# 3.0 with generics is awash in angle brackets and type annotations. </li></ul><ul><li>C# 4.0 has tuples, but clunky and no pattern matching </li></ul><ul><li>Can't have generic type parameters to Func<> delegates – must be class members </li></ul>Func<Func<T,U,bool>,Func<T,U,Tuple<T,U>>,T,U,Tuple<T,U>> filtermap = (f, m, a, b) => { if (f(a,b)) { return m(a,b); } else { return Tuple.Create(a, b); } }; C# 3.0 – can't actually do this!
  • 16. C# 3.0 – can do this Func<Func<int,string,bool>, Func<int,string,Tuple<int,string>>,int,string, Tuple<int,string>> filtermap = (f, m, a, b) => { if (f(a,b)) { return m(a,b); } else { return Tuple.Create(a, b); } }; Func<int,string,bool> filter = ...; Func<int,string,Tuple<int,string>> map = ...; var t = filtermap(filter, map, 1, &quot;Hello&quot;); var tInt = t.Item1; var tString = t.Item2;
  • 17. <ul><li>C# 3.0 can also do this – method signature </li></ul>class C { public Tuple<T, U> Filtermap<T,U>( Func<T,U,bool> f, Func<T,U,Tuple<T,U>> m, T a, U b) { if (f(a, b)) { return m(a, b); } else { return Tuple.Create(a, b); } } } C# 3.0
  • 18. C# 3.0/4.0 – a lot better than Java, but still not a full functional language “ Mads Torgersen, C# Product Manager http://blogs.msdn.com/b/madst/archive/2007/01/23/is-c-becoming-a-functional-language.aspx People who are functional programmers by night and have to write C# by day will find that the daily headache sets in a little later in the afternoon.
  • 19. <ul><li>But look at F#! No type annotations needed at all </li></ul><ul><li>Can be a class member or just nested function </li></ul><ul><li>No angle bracket mess </li></ul>class C { public Tuple<T, U> Filtermap<T,U>( Func<T,U,bool> f, Func<T,U,Tuple<T,U>> m, T a, U b) { if (f(a, b)) { return m(a, b); } else { return Tuple.Create(a, b); } } } C# 3.0 let filtermap f m a b = if f(a,b) then m(a,b) else (a,b) val filtermap : ('a * 'b -> bool) -> ('a * 'b -> 'a * 'b) -> 'a -> 'b -> 'a * 'b F#
  • 20. <ul><li>Scala: Still need to add type annotations, though syntax cleaner than C# </li></ul>let filtermap f m a b = if f(a,b) then m(a,b) else (a,b) val filtermap : ('a * 'b -> bool) -> ('a * 'b -> 'a * 'b) -> 'a -> 'b -> 'a * 'b F# def filtermap[T,U](f: T * U => Boolean, m: T * U => T * U, a : T, b : U) : T * U = { if (f(a,b)) { m(a, b) } else { (a, b) } } Scala
  • 21. <ul><li>Somewhat contrived example, but power of F# type inference </li></ul>Func<Func<T,U>,Func<U,U,V>,T,T,V> f = (g,h,a,b) => { return h(g(a), g(b)); }; C# 3.0 let f g h a b = h (g a) (g b) val f : ('T -> 'U) -> ('U -> 'U -> 'V) -> 'T -> 'T -> 'V F# def f[T,U,V] (g : (T) => U, h : (U, U) => V, a : T, b : T) : V = { h(g a, g b) } Scala
  • 22. <ul><li>Without inline keyword, function may be less generic than desired </li></ul><ul><li>If inline keyword used, compiler auto-generates generic constraint, then inserts function inline everywhere the function is called based on current context </li></ul>// No inline keyword – not generic let add a b = a + b val add : int -> int -> int let inline add a b = a + b val inline add : ^a -> ^b -> ^c when (^a or ^b) : (static member ( + ) : ^a * ^b -> ^c) let myInt = add 1 2 val myInt : int = 3 let myFloat = add 1.0 2.0 val myFloat : float = 3.0
  • 23. <ul><li>Mixed paradigm: OO and Functional </li></ul><ul><li>However, F# is much more focused on Functional </li></ul><ul><li>Scala has more sophisticated OO system </li></ul><ul><li>F# has: </li></ul><ul><li>Classes </li></ul><ul><li>Structs (value types) </li></ul><ul><li>Interfaces </li></ul><ul><li>Abstract base classes </li></ul><ul><li>Object expressions </li></ul><ul><li>Single inheritance, but multiple inheritance of interfaces </li></ul><ul><li>Nothing quite like Scala Traits </li></ul><ul><li>Conversions are explicit – for example you must cast an object to an interface to use the interface-specific methods </li></ul><ul><li>F# discourages the use of deep inheritance hierarchies, opting for more functional approach </li></ul><ul><li>F# does not have protected members – only private, public, internal </li></ul>
  • 24. <ul><li>F# tends to de-emphasize lots of OO </li></ul><ul><li>Record types – lightweight data structure similar to Scala case classes </li></ul><ul><li>Can also contain lambdas </li></ul>// Car as an F# record type CarRecord = { Make : string Model : string Year : int Color : string } let m3 = { Make = &quot;BMW&quot;; Model = &quot;M3&quot;; Year = 2011; Color = &quot;MetallicPebbleGray&quot; } let m5 = { m3 with Model = &quot;M5&quot;; Color = &quot;Crimson&quot; } // Scala: case class Car(make:String, model:String, year:Int, Color:String);
  • 25. <ul><li>F# tends to de-emphasize lots of OO </li></ul><ul><li>Record types – lightweight data structure similar to Scala case classes </li></ul><ul><li>Can also contain lambdas/function values – this can be an effective technique similar to DI </li></ul>// MovingCar is an F# record that can drive type MovingCar = { Make : string Model : string Year : int Color : string Drive : unit -> unit } let m3 = { Make = &quot;BMW&quot;; Model = &quot;M3&quot;; Year = 2011; Color = &quot;MetallicPebbleGray&quot;; Drive = fun () -> printfn(&quot;Vroom&quot; } let m5 = { m3 with Model = &quot;M5&quot;; Color = &quot;Crimson&quot;; Drive = fun () -> printfn &quot;Vroom VROOM!!&quot; }
  • 26. <ul><li>Constructors where parameters become auto-generated fields/properties </li></ul>// Car as an F# type (.NET class) // Doesn't compile - &quot;make&quot; is not mutable! type Car(make : string, model : string, year : int, color : string) = member x.Make with get() = make and set(v) = make <- v type Car(make : string, model : string, year : int, color : string) = let mutable _make = make member x.Make with get() = _make and set(v) = _ make <- v
  • 27. <ul><li>Lightweight, powerful approach instead of OO </li></ul><ul><li>&quot;Discriminators&quot; could also be function values </li></ul><ul><li>This example also shows &quot;typedef&quot;-style declarations </li></ul>type Make = string type Model = string type TrainLine = Orange | Red | Green | Purple | Silver type Route = int type Transport = | Car of Make * Model | Train of TrainLine | Bicycle | Bus of Route | Walking let alice = Car(&quot;BMW&quot;, &quot;M5&quot;) let bob = Train(Orange) let carol = Bicycle let dave = Bus(42) let peggy = Walking
  • 28. <ul><li>Pattern matching on Discriminated Unions </li></ul>let averageSpeed (t : Transport) = match tr with | Car(make,model) when make = &quot;BMW&quot; -> 90 | Car _ -> 55 | Bicycle -> 18 | Bus _ -> 24 | Train(r) -> match r with | Orange | Red -> 28 | Green -> 13 | Purple -> 45 | Silver -> 18 | Walking -> 5
  • 29. <ul><li>More pattern matching + function keyword </li></ul>let averageSpeed = function | Car(make,model) when make = &quot;BMW&quot; -> 90 | Car _ -> 55 ... let f = function ... // same as let f x = match x with | ...
  • 30. <ul><li>Here we combine different kinds of weather with information specific to that weather type, including units of measure specific to that type of weather </li></ul>[<Measure>] type degree [<Measure>] type mm [<Measure>] type hr [<Measure>] type inch [<Measure>] type mile type WeatherType = | Sunny of float<degree> | Rainy of float<mm/hr> | Snowy of float<inch/hr> | Cloudy of float<mile> // visibility | Thunderstorms let drizzle = Rainy(1.0) // ERROR: won't compile! let sleet = Snowy(2.0<mm/hr>) // ERROR: won't compile!
  • 31. <ul><li>Mixed paradigm: OO and Functional </li></ul><ul><li>However, F# is much more focused on Functional </li></ul><ul><li>Scala has more sophisticated OO system </li></ul>// Interface - // this is inferred due to all properties/methods being abstract // Note, cannot have &quot;traits&quot; with implementation // Closest thing would be an abstract base class type IAnimal =     abstract Name : string with get     abstract Age  : int with get,set     abstract Talk : unit -> unit     abstract Move : unit -> unit
  • 32. <ul><li>Classes </li></ul>// Class type BaseAnimal(name, talk, move) =     let mutable age = 0     // &quot;do&quot; expressions - part of constructor     do printfn &quot;Constructing animal %s who says %s&quot; name talk     // alternate constructor     new(name) = BaseAnimal(name, &quot;Hello&quot;, &quot;Walk&quot;)          interface IAnimal with         member x.Name with get() = name         member x.Age with get() = age and set(v) = if v >= 0 then age <- v         member x.Talk() = printfn &quot;%s&quot; talk         member x.Move() = printfn &quot;%s&quot; move // Deriving from base type type Owl(name) = inherit BaseAnimal(name, &quot;Scrreeech&quot;, &quot;Swoooop&quot;) type Turkey(name) = inherit BaseAnimal(name, &quot;Gobble gobble&quot;, &quot;Flap flap&quot;)
  • 33. <ul><li>Classes, Interface casting, Object Expressions </li></ul>let chicken =  BaseAnimal(&quot;Henery&quot;,     &quot;Bwock bwock bwock&quot;, &quot;Shuffle shuffle&quot;) let moose   = BaseAnimal(&quot;Bullwinkle&quot;, &quot;Dum de dum&quot;,        &quot;Loaf shuffle loaf&quot;) // Have to cast to IAnimal! // moose.Talk() - won't compile let imoose = moose :> IAnimal imoose.Talk() imoose.Move() // Object expression - define interface &quot;inline&quot; let horse(name) =      let age = ref 0    // reference type - closure     { new IAnimal with         member x.Name with get() = name         member x.Age with get() = !age and set(v) = if v >= 0 then age := v         member x.Talk() = printfn &quot;Neigh&quot;         member x.Move() = printfn &quot;Gallop&quot; } let quickDraw = horse(&quot;McGraw&quot;) quickDraw.Age <- 10
  • 34. <ul><li>Abstract Base Class </li></ul>// Abstract base class [<AbstractClass>] type AbstractBird(name) as this =     let mutable age = 0     abstract Name : string with get     default this.Name with get() = name     abstract Age  : int with get,set     default this.Age with get() = age and set(v) = age <- v     abstract Talk : unit -> unit     abstract Fly  : unit -> unit     interface IAnimal with         member x.Name with get() = this.Name         member x.Age with get() = this.Age and set(v) = this.Age <- v         member x.Talk() = this.Talk()         member x.Move() = this.Fly()
  • 35. <ul><li>Abstract Base Class Inheritance </li></ul>type Eagle(title, name) =     inherit AbstractBird(name)     override this.Name with get() = title + &quot; &quot; + name     override x.Talk() = printfn &quot;Arrrrr&quot;     override x.Fly()  = printfn &quot;Swoop&quot; let e = Eagle(&quot;Lord&quot;, &quot;Gwaihir&quot;) // Don't have to cast to IAnimal e.Talk() e.Fly() // IAnimal can Move() but not Fly() let ie = e :> IAnimal ie.Move() // ie.Fly() - won't compile
  • 36. <ul><li>Target major platforms, leverage existing ecosystems: F#: .NET CLR/Mono, use C# libraries; Scala: JVM and some .NET, use Java libraries </li></ul><ul><li>This helps drive adoption vs. some other functional languages </li></ul>
  • 37. <ul><li>F# has good support for generics including constraints </li></ul><ul><li>F# 2.0 does not have variance indicators (i.e. unlike Scala [+T] [-T]) </li></ul>// Built in generic constraints type Comparator<'T when 'T : comparison>() =     member x.Compare (t1 : 'T) (t2 : 'T) = compare t1 t2      type Filter<'T when 'T : equality>(t1 : 'T) =     member x.Equals (t2 : 'T) = t1 = t2 // Type inference of generic parameter let f = Filter<_>(42) let res1 = f.Equals(2)
  • 38. <ul><li>F# has good support for generics including constraints </li></ul><ul><li>F# 2.0 does not have variance indicators (i.e. unlike Scala [+T] [-T]) </li></ul>// User defined generic constraints type Base(n) =     let mutable name = n     member x.Name with get() = name and set(v) = name <- v type Derived(n) =     inherit Base(n) let setName (c : 'T when 'T :> Base) s = c.Name <- s let b = Base(&quot;Base&quot;) let d = Derived(&quot;Derived&quot;) setName b &quot;NewBase&quot; setName d &quot;NewDerived&quot;
  • 39. <ul><li>Great support in F# for operator definition, very nice syntax </li></ul><ul><li>Makes it easy to define &quot;local&quot; operators </li></ul><ul><li>Some examples throughout presentation </li></ul>let (!!) a b = (a + 2) * b !! 1 2 val it : int = 6
  • 40. <ul><li>F# has great support </li></ul><ul><li>See Discriminated Unions </li></ul><ul><li>See Active Patterns below – F#-specific feature </li></ul>
  • 41. <ul><li>Tail call optimization </li></ul><ul><li>F# support this both through the compiler and CLR. The compiler transforms tail recursive call into while loops, etc. </li></ul><ul><li>The 64 bit CLR jitter can perform TCO from the raw IL. So C# code running on 64 bit may get TCO </li></ul><ul><li>JVM does not support TCO </li></ul><ul><li>Scala compiler performs TCO in some (many?) cases </li></ul><ul><li>Scala 2.8 adds the @tailrec annotation which emits a warning if scalac cannot optimize </li></ul>
  • 42. <ul><li>Example of various things discussed so far </li></ul>let numbers = [ 1; 2; 3; 4; 5; 6; 7; 8; 9 ] let rec sum acc (xs : int list) =     match xs with     | [] -> acc     | h :: t -> sum (acc + h) t let total = sum 0 numbers let rec sum2<'T> adder (acc : 'T) (xs : 'T list) =     match xs with     | [] -> acc     | h :: t -> sum2 adder (adder acc h) t let total1 = sum2 (+) 0 numbers let myColors = [ &quot;Red&quot;; &quot;Green&quot;; &quot;Blue&quot;; &quot;Purple&quot;; &quot;Orange&quot; ] let addStrings (s0 : string) (s1 : string) = System.String.Join(&quot;, &quot;, [| s0; s1 |]) let sumOfColors = sum2 addStrings &quot;&quot; myColors
  • 43. let arr = [| 1; 2; 3; 4; 5 |] let list = [ for i in 0 .. 2 .. 24 -> i * 4 ] type Country = { Name : string; Cities: string seq } let countries = [ { Name = &quot;Spain&quot;; Cities = [&quot;Barcelona&quot;; &quot;Madrid&quot; ] } { Name = &quot;Germany&quot;; Cities = [&quot;Berlin&quot;; &quot;Frankfurt&quot; ] } { Name = &quot;USA&quot;; Cities = [&quot;Boston&quot;; &quot;New York ] } { Name = &quot;India&quot;; Cities = [&quot;Bhopal&quot;; &quot;Mumbai&quot; ] } ] let populations : IDictionary<string,long> = ... let mySeq = seq { for c in countries do for city in c.Cities do if city.StartsWith(&quot;b&quot;) then let pop = populations.[&quot;city&quot;] yield city, country, pop }
  • 44. mySeq |> Seq.filter (fun (_,_,pop) -> pop > 1000000) |> Seq.sortBy (fun (_,_,pop) -> -pop) // descending |> Seq.map (fun (city,c,pop) -> sprintf &quot;%s, %s. Pop.: %d&quot; city c pop)
  • 45. <ul><li>Pipelining operator defined as: </li></ul>[ 1; 2; 3; 4; 5 ] |> List.map (fun x -> x * 2) // is the same as: List.map (fun x -> x * 2) [ 1; 2; 3; 4; 5 ] let (|>) x f = f x
  • 46. <ul><li>Pipelining </li></ul>let arr = [| 1; 2; 3; 4; 5 |] arr |> Array.partition (fun x -> x % 2 = 0) |> fst |> Array.map (fun x -> x * 2) |> Array.filter (fun x -> x > 4) |> Array.iter (fun x -> printfn &quot;Value: %d&quot; x) let isEven x = x % 2 = 0 let pv x = printfn &quot;Value: %d&quot; x [| 1; 2; 3; 4; 5 |] |> Array.partition isEven |> fst |> Array.map (( * ) 2) |> Array.filter ((<) 4) // backwards, i.e. 4 < x |> Array.iter pv <ul><li>“ Point-free” style: </li></ul>
  • 47. <ul><li>Function composition operator defined as: </li></ul>// inline need else F# will assume ints let inline square a = a * a let inline multiply a b = a * b let inline add a b = a + b let add10 = add 10 let mult7 = multiply 7 let g = square >> add10 >> mult7 let squaredPlus10 = [ 1; 2; 3; 4; 5 ] |> List.map g let addFloat = add 123.456 let multiPi = multiply 3.14159 let h = square >> addFloat >> multiPi let items = [ 1.1; 2.2; 3.3; 4.4; 5.5 ] |> List.map h let (>>) f g x = g(f(x))
  • 48. <ul><li>Map, filter, fold, reduce and friends </li></ul><ul><li>append, average, cache, cast, choose, collect, concat, countBy, create, delay, distinct, empty, exists, exists2, fill, filter, find, findIndex, fold, foldBack, fold2, foldBack2, forall, groupBy, head, init, initInfinite, isEmpty, iter, iteri, iter2, length, map, mapi, map2, map3, max, maxBy, min, minBy, nth, ofArray, ofList, ofSeq, pairwise, permute, pick, readonly, reduce, reduceBack, replicate, rev, scan, scanBack, singleton, skip, skipWhile, sort, sortBy, sortWith, sum, sumBy, tail, take, takeWhile, toArray, toList, toSeq, tryFind, tryFindIndex, truncate, unfold, unzip, unzip3, windowed, zip, zip3 </li></ul>[ 1; 2; 3; 4; 5 ] |> List.map (( * ) 2) |> List.reduce (fun acc elem -> acc + elem) [ &quot;one&quot;; &quot;two&quot;; &quot;three&quot;; &quot;four&quot;; &quot;five&quot; ] |> List.map (fun s -> s.ToUpperCase()) |> List.reduce (fun acc elem -> acc + &quot;, &quot; + elem)
  • 49. let mapReduce() =     [ 1; 2; 3; 4; 5 ]     |> List.map (( * ) 2)     |> List.reduce (fun acc elem -> acc + elem) let res = mapReduce() val it : int = 30 let words = [ &quot;one&quot;; &quot;two&quot;; &quot;three&quot;; &quot;four&quot;; &quot;five&quot; ] let flatMapDistinctToUpperSorted() =     let chars =          words         |> List.map (fun w -> w.ToCharArray() |> List.ofArray)         |> Seq.ofList // Seq needed for certain functions         |> Seq.concat // flatten         |> Seq.distinct         |> Seq.map (fun c -> System.Char.ToUpper(c))         |> Seq.sort     chars let res2 = flatMapDistinctToUpperSorted() val it : seq<char> = seq ['E'; 'F'; 'H'; 'I'; ...]
  • 50. <ul><li>Partial function application/currying – example above also using function composition </li></ul>
  • 51. <ul><li>Reflection – F# uses underlying .NET reflection, very powerful </li></ul><ul><li>Nice pattern matching syntax, also works with Exceptions </li></ul>type IShape() = ... // interface match getShape() with | :? Triangle t -> printfn &quot;It's a triangle&quot; | :? Circle c -> printfn &quot;Circle with radius %f&quot; c.Radius | :? Rectangle r -> printfn &quot;Rectangle of area %f&quot; r.Width * r.Length | _ -> failwith &quot;Unknown shape!&quot; try failingOperation() with | :? IOException ioex -> printfn &quot;IO Problem: %s&quot; ioex.Message | :? NullReferenceException _ -> printfn &quot;Billion dollar problem!&quot; | exn -> printfn &quot;Some unknown problem: %s&quot; exn.Message
  • 52. <ul><li>Point-free style – examples shown throughout presentation </li></ul>
  • 53. <ul><li>Annotations/metadata – use underlying .NET and Java support </li></ul>
  • 54. <ul><li>REPL: F# Interactive </li></ul><ul><li>Part of Visual Studio or standalone console </li></ul>
  • 55. /// These are auto-doc comments – F# has this feature but not C# type MyClass() = ... // same as... /// <summary>These are auto-doc comments like C#</summary> type MyClass() = ... // Can also use all .NET XML doc elements /// <summary>Explicit style</summary> /// <remarks>...</remarks> type OtherClass() = /// <summary>Add two numbers together</summary> /// <param name=&quot;i0&quot;>The first number</param> /// <param name=&quot;i1&quot;>The second number</param> member x.Add(i0, i1) = i0 + i1 <ul><li>.NET XML document generation </li></ul><ul><li>In addition to C#-style comments, F# adds shortcut if just /// </li></ul><ul><li>Lots more tags than shown here </li></ul>
  • 56. <ul><li>Somewhat similar to Scala Actors </li></ul><ul><li>See code for full example </li></ul>open System type Ticket = int64 type AccountResult = | Success | Failure of string let res2String = function     | Success -> &quot;Success&quot;     | Failure(s) -> &quot;Failure: &quot; + s type AuditMessage = { ID : Ticket; AccountName : string; Action : string; Amount : decimal; Date : DateTime; Result : AccountResult }     with member x.AsString with get() =  sprintf &quot;ID: %d, Account: %s, Action: %s, Amount: %M, Date: %A, Result: %s&quot; x.ID x.AccountName x.Action x.Amount x.Date (x.Result |> res2String)
  • 57. <ul><li>See code example </li></ul>// Packets within the MailboxProcessor type Packet = | Echo of string * AsyncReplyChannel<string> | AuditReportRequest of AsyncReplyChannel<string> | Deposit of string * decimal * AsyncReplyChannel<AuditMessage> // Account name, amount | Withdrawal of string * string * decimal * AsyncReplyChannel<AuditMessage>   // Account name, withdrawer, amount | NumMessages of AsyncReplyChannel<Ticket> | Stop // Message request for Scala-style syntax type MessageRequest = | EchoRequest of string | AuditReportRequestMsg | DepositRequest of string * decimal | WithdrawalRequest of string * string * decimal | MessageCountRequest | StopRequest type Reply = | ReplyString of string | ReplyMessage of AuditMessage
  • 58. <ul><li>See code example </li></ul>// Convert Reply to inner value let getReply = function  ReplyString(s) -> s | ReplyMessage(msg) -> msg.AsString let getMsg   = function ReplyMessage(msg) -> msg | _ -> failwith &quot;Only call getMsg when expecting a ReplyMessage&quot; /// Our highly sophisticated, iron-clad, thread-unsafe bank account type Account(name, startAmount : decimal) =     let mutable balance = startAmount     member x.Name with get() = name     member x.Deposit amount =         balance <- balance + amount         Success     member x.Withdraw amount =         if amount > balance then             Failure(&quot;Insufficient funds!&quot;)         else             balance <- balance - amount             Success
  • 59. <ul><li>See code example </li></ul>/// Agent that wraps a MailboxProcessor &quot;workflow&quot; with audit messages etc. type AccountAgent(accounts : seq<Account>) =     let mutable auditMessages : AuditMessage list = []     let accountMap = accounts |> Seq.map (fun a -> a.Name, a) |> dict     let EmptyTicket = 0L     let addMsg (t, name,action,amount,result) =         let msg = { ID = t; AccountName = name; Action = action; Amount = amount; Date = DateTime.Now; Result = result }         auditMessages <- msg :: auditMessages         msg
  • 60. <ul><li>See code example </li></ul>     /// Create a report from the audit messages     let createReport() =         let arr =              auditMessages             |> List.rev             |> List.map (fun a -> sprintf &quot;[%A] Account %s: %s of $%M %s&quot; a.Date a.AccountName a.Action a.Amount (res2String a.Result))             |> Array.ofSeq         &quot;AUDIT: &quot; + System.String.Join(&quot;rn&quot;, arr)
  • 61.      /// Our asynchronous agent processor - skeleton     let agent = MailboxProcessor.Start(fun inbox ->         let rec loop ticket =             async {                 let! msg = inbox.Receive()                 match msg with                 | Echo(echo, channel) -> // ...                     return! loop (ticket + 1L)                 | AuditReportRequest(channel) -> // ...                 | NumMessages(channel) -> // ...                 | Deposit(name,amt,channel) ->  // ...                     return! loop (ticket + 1L)                 | Withdrawal(name,withdrawer,amt,channel) -> // ...                     return! loop (ticket + 1L)                 | Stop -> () // stop looping             }         loop EmptyTicket)
  • 62.      /// Our asynchronous agent processor     let agent = MailboxProcessor.Start(fun inbox ->         let rec loop ticket =             async {                 let! msg = inbox.Receive()                 match msg with                 | Echo(echo, channel) ->                     channel.Reply(&quot;ECHO: &quot; + echo)                     return! loop (ticket + 1L)                 | AuditReportRequest(channel) ->                     channel.Reply(createReport())                     return! loop (ticket + 1L)                 | NumMessages(channel) ->                     channel.Reply(n)                     return! loop (ticket + 1L)
  • 63.      /// Our asynchronous agent processor     let agent = MailboxProcessor.Start(fun inbox ->         let rec loop ticket =             async {                 let! msg = inbox.Receive()                 match msg with // ...                | Deposit(name,amt,channel) ->                      let t = ticket                     if accountMap.ContainsKey(name) then                         let a = accountMap.[name]                         a.Deposit(amt) |> ignore                         let msg = addMsg (t, name, &quot;Deposit&quot;, amt, Success)                         channel.Reply(msg)                     else                         let msg = addMsg  (t, name, &quot;Deposit&quot;, amt,  Failure(&quot;Account &quot; + name + &quot; not found&quot;))                         channel.Reply(msg)                     return! loop (ticket + 1L)
  • 64. // Scala style syntax helper - almost let (<!) (a : AccountAgent) (req : MessageRequest) = a.SendMessage req let agent = new AccountAgent(bankAccounts) let s = agent.Echo(&quot;Hello world!&quot;) let mutable n = agent.MessageCount() printfn &quot;Messages: %d&quot; n printfn &quot;Making deposits...&quot; agent <! DepositRequest(&quot;Alice&quot;, 1200M) |> ignore agent <! DepositRequest(&quot;Bob&quot;,  200M)  |> ignore agent <! DepositRequest(&quot;Carol&quot;, 300M)  |> ignore agent <! DepositRequest(&quot;Dave&quot;,  400M)  |> ignore n <- agent <! MessageCountRequest |> getReply |> int64 printfn &quot;Messages: %d&quot; n
  • 65. <ul><li>F# great language for DSLs </li></ul><ul><li>Discriminated Unions, operators, combinators, whitespace, &quot;``&quot; </li></ul><ul><li>Example by Dmitri Nesteruk, http://www.codeproject.com/KB/dotnet/dslfsharp.aspx </li></ul>project &quot;F# DSL Article&quot; starts &quot;01/01/2009&quot; resource &quot;Dmitri&quot; isa &quot;Writer&quot; with_rate 140 resource &quot;Computer&quot; isa &quot;Dumb Machine&quot; with_rate 0 group &quot;DSL Popularization&quot; done_by &quot;Dmitri&quot; task &quot;Create basic estimation DSL&quot; takes 1 day task &quot;Write article&quot; takes 1 day task &quot;Post article and wait for comments&quot; takes 1 week group &quot;Infrastructure Support&quot; done_by &quot;Computer&quot; task &quot;Provide VS2010 and MS Project&quot; takes 1 day task &quot;Download and deploy TypograFix&quot; takes 1 day task &quot;Sit idly while owner waits for comments&quot; takes 1 week prepare my_project
  • 66. <ul><li>Another example – NaturalSpec by Navision (Steffen Forkmann et al) </li></ul><ul><li>BDD unit testing framework </li></ul><ul><li>' is a legal F# identifier </li></ul><ul><li>`` allows spaces inside legal F# identifiers </li></ul>[<Scenario>] let ``When removing an element from a list it should not contain the element``() =   Given [1;2;3;4;5]                 // &quot;Arrange&quot; test context     |> When removing 3              // &quot;Act&quot;     |> It shouldn't contain 3       // &quot;Assert&quot;     |> It should contain 4          // another assertion     |> It should have (Length 4)    // Assertion for length     |> It shouldn't have Duplicates // it contains duplicates ?     |> Verify                       // Verify scenario
  • 67. <ul><li>Yet another BDD example – FsUnit open source unit test framework (fsunit.codeplex.com) </li></ul>true |> should be True false |> should not (be True) [] |> should be Empty [1] |> should not (be Empty) (fun () -> failwith &quot;BOOM!&quot; |> ignore) |> should throw typeof<System.Exception> type LightBulb(state) = member x.On = state override x.ToString() = match x.On with | true -> &quot;On&quot; | false -> &quot;Off&quot; [<TestFixture>] type ``Given a LightBulb that has had its state set to true`` ()= let lightBulb = new LightBulb(true) [<Test>] member test. ``when I ask whether it is On it answers true.`` ()= lightBulb.On |> should be True [<Test>] member test. ``when I convert it to a string it becomes &quot;On&quot;.`` ()= string lightBulb |> should equal &quot;On&quot;
  • 68. // Simple Active Pattern – returns a boolean let (|UpperChar|) c = Char.ToUpper(c) // Partial Active Pattern – Some (with possible transformation) // or None let (|IsDigit|_|) c = if Char.IsDigit(c) then Some(int c) // convert char to an int else None // Active Pattern with parameters + reusing above APs let (|IsDigitInRange|_|) rangeStart rangeEnd c = match c with | IsDigit(n) -> if n >= rangeStart && n <= rangeEnd then Some(n) else None | _ -> None
  • 69. // Partial Active Pattern let (|Match|_|) (regex : Regex) input =     if regex.IsMatch(input) then         Some(regex.Match(input))     else None // Active pattern - // &quot;partitions&quot; input into one of several &quot;classes&quot; let (|Zip|Country|State|City|Invalid|) s =   match s with | Match regexZip m     -> Zip(m |> result &quot;zip&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;) | Match regexCity m -> City(&quot;&quot;,resCountry m,resState m,m |> result &quot;city&quot;) | Match regexState m  -> State(&quot;&quot;, resCountry m, resState m, &quot;&quot;) | Match regexCountry m -> Country(&quot;&quot;, resCountry m, &quot;&quot;, &quot;&quot;) | _                    -> Invalid
  • 70. // Using Active Pattern, this is simplified let parse input = match input with | Zip(z, _, _, _)     -> { Country = &quot;&quot;; State = &quot;&quot;; City = &quot;&quot;; Zip = z } | Country(_, c, _, _) -> { Country = c;  State = &quot;&quot;; City = &quot;&quot;; Zip = &quot;&quot; } | State(_, c, s, _)   -> { Country = c;  State = s;  City = &quot;&quot;; Zip = &quot;&quot; } | City(_, co, st, ci) -> { Country = co; State = st; City = ci; Zip = &quot;&quot; } | Invalid             -> { Country = &quot;&quot;; State = &quot;&quot;; City = &quot;&quot;; Zip = &quot;&quot; }
  • 71. // Partial Active Pattern - returns Option. If Some(_) then returns a LocationInfo let (|ValidLocation|_|) input =     match input with     | Zip(z, _, _, _)     -> Some({ Country = &quot;&quot;; State = &quot;&quot;; City = &quot;&quot;; Zip = z })     | City(_, co, st, ci) -> Some({ Country = co; State = st; City = ci; Zip = &quot;&quot; })     | _                   -> None // Is this a &quot;valid&quot; location? // Use of &quot;function&quot; let parseIsValid = function     | ValidLocation(loc) -> true     | _                  -> false // Same as... let parseIsValid2 input =      match input with     | ValidLocation(loc) -> true     | _                  -> false
  • 72. // Partial/Parameterized Active Pattern // Does this have a zip code contained in zipList? let (|HasZip|_|) (zipList : string list) input =     match input with     | Zip(z, _, _, _) when (zipList |> List.exists (fun x -> x = z)) -> Some(z)     //| City(_, co, st, ci)          -> None  // could do a lookup here...     | _                                                              -> None let isBoston input =     // 02101 - 02299     let bostonZips = [ for i in 2101 .. 2299 -> sprintf &quot;0%d&quot; i ]      match input with     | HasZip bostonZips z -> true     | _                   -> false     
  • 73. <ul><li>Nice helper which looks like it’s accessing a property but really performs a function based on a string </li></ul><ul><li>Saves a bit of typing plus you can add some error handling in definition </li></ul><ul><li>Caveat: May fail at runtime, not compile time </li></ul><ul><li>This example is WPF/Silverlight/XAML related </li></ul>let (?) (source:obj) (s:string) =         match source with          | :? ResourceDictionary as r ->  r.[s] :?> 'T         | :? Control as source ->              match source.FindName(s) with … Usage: let ic : ItemsControl = this?ic Instead of: let ic = this.FindName(&quot;ic&quot;) :?> ItemsControl
  • 74. <ul><li>Modules allow you to write static functions then call them without Class-Dot syntax (like you would in C# or Java) </li></ul><ul><li>Great for “operator-like” functions </li></ul><ul><li>One of those nice little things in F# that add up and make code more succinct and elegant </li></ul><ul><li>Scala Predef, apply can perform similar function </li></ul>[<AutoOpen>] module private Utilities =  let rgb r g b = Color.FromArgb(0xFFuy, r |> byte, g |> byte, b |> byte) let argb a r g b = Color.FromArgb(a |> byte, r |> byte, g |> byte, b |> byte) // Usage: let colorError    = rgb 0xFF 0xE4 0xE1 // MistyRose // Instead of: let colorError    = Utilities.rgb 0xFF 0xE4 0xE1 // MistyRose
  • 75. open System.Drawing open System.Windows.Forms let form = new Form(Text = &quot;F# Windows Form&quot;,                     Visible = true,                     TopMost = true) let rect = Rectangle(100, 100, 200, 250) let lineSegments = new ResizeArray<Point * Point>() // Hook into Form's MouseMove handler // Filter within particular area, get &quot;line segments&quot; between clicks form.MouseMove     |> Event.filter (fun evArgs -> rect.Contains(evArgs.X, evArgs.Y))     |> Event.pairwise     |> Event.add (fun (ev1,ev2) -> lineSegments.Add(ev1.Location, ev2.Location)) <ul><li>Functional way of handling events – canonical example is GUI but many other uses </li></ul><ul><li>You can perform filter, map, partition, scan, etc. </li></ul><ul><li>You can also &quot;publish&quot; events and expose them as properties in a class that others can subscribe to, plus trigger events </li></ul>
  • 76. // Partition between left/other mouse button clicked (within rect) // Map does a transform // Add changes text, plus difference background color depending on which // mouse button clicked let buttonLeft, buttonRight =     form.MouseClick     |> Event.filter  (fun evArgs -> rect.Contains(evArgs.X, evArgs.Y))     |> Event.partition (fun evArgs -> evArgs.Button = MouseButtons.Left) buttonLeft |> Event.map (fun evArgs -> sprintf &quot;Left mouse clicked at (%d,%d) at %A&quot; evArgs.X evArgs.Y DateTime.Now) |> Event.add (fun s -> form.Text <- s; form.BackColor <- Color.Lime) buttonLeft |> Event.map (fun evArgs -> sprintf &quot;Right mouse clicked at (%d,%d) at %A&quot; evArgs.X evArgs.Y DateTime.Now) |> Event.add (fun s -> form.Text <- s; form.BackColor <- Color.Red) <ul><li>Functional way of handling events – canonical example is GUI but many other uses, e.g. pub/sub </li></ul><ul><li>You can perform filter, map, partition, scan, etc. </li></ul><ul><li>You can also &quot;publish&quot; events and expose them as properties in a class that others can subscribe to, plus trigger events </li></ul>
  • 77. [<AbstractClass>] type BasePublisher() as this =     let changed = new Event<string>()     member internal x.NotifyAction s = changed.Trigger(s)     member x.PropertyChanged = changed.Publish // Let's not worry about locking for now! type Account(startAmount) as this =     inherit BasePublisher()     let mutable balance = startAmount     let notify s amt =         let msg = sprintf &quot;%s of $%d at %A&quot; s amt DateTime.Now         this.NotifyAction(msg)          member x.Deposit amount =         balance <- balance + amount         notify &quot;Deposit&quot; amount     member x.Withdraw amount =         if amount > balance then             notify &quot;ERROR Withdrawal attempt&quot; amount         else             balance <- balance - amount             notify &quot;Withdrawal&quot; amount <ul><li>Simple example of pub/sub – account with &quot;auditors&quot; </li></ul>
  • 78. type Auditor(name) =     let messages = new ResizeArray<string>()     let messageReceived s =          messages.Add(s)         printfn &quot;%s received: %s&quot; name s     member x.MessageReceived s = messageReceived s let execute() =     let account = Account(1000)     let auditor1 = Auditor(&quot;Auditor 1&quot;)     let auditor2 = Auditor(&quot;Auditor 2&quot;)     account.PropertyChanged |> Event.add (fun s -> auditor1.MessageReceived(s))     account.PropertyChanged         |> Event.filter (fun s -> s.StartsWith(&quot;ERROR&quot;))         |> Event.add (fun s -> auditor2.MessageReceived(s))     account.Deposit(500)     account.Withdraw(700)     account.Withdraw(4000) execute() <ul><li>Continued example of pub/sub – account with &quot;auditors&quot; </li></ul>
  • 79. // From Don Syme, http://blogs.msdn.com/b/dsyme/archive/2007/10/11/introducing-f-asynchronous-workflows.aspx let exampleSync() =     let task1 = (fun () -> 10 + 10)     let task2 = (fun () -> 20 + 20)     [ task1; task2 ] |> List.iter (fun f -> f() |> ignore) let exampleAsync() =     let task1 = async { return 10 + 10 }     let task2 = async { return 20 + 20 }     Async.RunSynchronously (Async.Parallel [ task1; task2 ]) <ul><li>In simplest form, allow you to take synchronous workflows and convert to async with minimal effort </li></ul><ul><li>Adapted from Don Syme </li></ul><ul><li>http://blogs.msdn.com/b/dsyme/archive/2007/10/11/introducing-f-asynchronous-workflows.aspx </li></ul>
  • 80. // Adapted from http://msdn.microsoft.com/en-us/library/dd233250.aspx#Y267 let urlList = [ &quot;Microsoft.com&quot;, &quot;http://www.microsoft.com/&quot;                 &quot;MSDN&quot;, &quot;http://msdn.microsoft.com/&quot;                 &quot;Bing&quot;, &quot;http://www.bing.com&quot;               ] let fetchSync(name, url:string) =     try         printfn &quot;Getting %s...&quot; name         let uri = new System.Uri(url)         let webClient = new WebClient()         let html = webClient.DownloadString(uri)         printfn &quot;Read %d characters for %s&quot; html.Length name     with         | ex -> printfn &quot;%s&quot; (ex.Message); let runAllSync() =     for (name,url) in urlList do         fetchSync(name, url) runAllSync() // Real: 00:00:02.601, CPU: 00:00:00.062, GC gen0: 0, gen1: 0, gen2: 0 <ul><li>Example doing network I/O, here's the synchronous version </li></ul>
  • 81. let fetchAsync(name, url:string) =     async {          try             let uri = new System.Uri(url)             let webClient = new WebClient()             let! html = webClient.AsyncDownloadString(uri)             printfn &quot;Read %d characters for %s&quot; html.Length name         with             | ex -> printfn &quot;%s&quot; (ex.Message);     } let runAllAsync() =     urlList     |> Seq.map fetchAsync     |> Async.Parallel      |> Async.RunSynchronously     |> ignore runAllAsync() // Real: 00:00:01.522, CPU: 00:00:00.078, GC gen0: 0, gen1: 0, gen2: 0 // 58% of sync time <ul><li>Network I/O, async version </li></ul><ul><li>Results not scientific but real (dual-core PC) </li></ul>
  • 82. <ul><li>This just scratches the surface of what you can do </li></ul><ul><li>Waiting, cancellation, continuations, much more </li></ul><ul><li>One case of a more general feature – workflows aka Computational Expressions </li></ul>
  • 83. <ul><li>No functional language would be complete without Monads! </li></ul><ul><li>F# has excellent support </li></ul><ul><li>See http://www.synqotik.net/blog/post/2011/01/23/Understanding-F-Workflows.aspx for my example </li></ul>/// A result of parsing which is either success in which values /// (probably ValueTokens) are returned, /// or failure with an error message and the Position where the failure occurred type ParseResult<'T> = | ParseSuccess of 'T | ParseFailure of string * Position /// The &quot;monadic type&quot; type ParseInfo<'T> = (unit -> ParseResult<'T>) /// Workflow utilities let runM (pinfo : ParseInfo<_>) = pinfo() let failM msg pos : ParseInfo<_> = (fun () -> ParseFailure(msg, pos)) let succeedM v : ParseInfo<_>    = (fun () -> ParseSuccess(v)) let bindM (pinfo : ParseInfo<'T>, rest : 'T -> ParseInfo<'U>) =     let result = runM pinfo     match result with     | ParseFailure(msg, pos) ->         failM msg pos     | ParseSuccess(v) ->         rest(v) let returnM v : ParseInfo<_> = succeedM v let zeroM () = failM &quot;&quot; { Line = 0; Column = 0 } let delayM f = (fun () -> runM (f()))
  • 84. <ul><li>Continued… </li></ul>/// The Parse workflow builder             type ParseBuilder() =     member x.Bind (pinfo : ParseInfo<'T>, rest : 'T -> ParseInfo<'U>) = bindM(pinfo, rest)     member x.Return v = returnM v     member x.ReturnFrom (pinfo : ParseInfo<'T>) = pinfo     member x.Zero () = zeroM()     member x.Delay(f) = delayM f /// Runs a Parse workflow /// This could also have additional members, for example to run multiple /// parse workflows in parallel and return the overall result, etc. type ParseRunner() =     static member Run(workflow : ParseInfo<_>) = workflow()     /// Run multiple workflows and return an overall result     static member RunAsync (workflows : #seq<ParseInfo<_>>) =         processParseListAsync workflows /// The Parse builder object, used for the computational expression parse { } syntax let parse = new ParseBuilder()
  • 85. <ul><li>Continued… </li></ul>// Create some format specifiers let dateValidator = Validator.Regex(@&quot;[1-9][0-9]{3}[0-1][0-9][0-3][0-9]&quot;) let  dt = { Name = &quot;date&quot;;   Format = A(8, &quot;&quot;);  Validator = dateValidator } let  x1 = { Name = &quot;_x1&quot;;       Format = X(2);   Validator = Validator.True } let  t = { Name = &quot;tempF&quot;; Format = F(6, 0.0);  Validator = Validator.Float } let  x2 = { Name = &quot;_x2&quot;;       Format = X(2);   Validator = Validator.True } let  p = { Name = &quot;pressure&quot;; Format = F(6, 0.0); Validator = Validator.Float } let  x3 = { Name = &quot;_x3&quot;;       Format = X(2);   Validator = Validator.True } let  rh = { Name = &quot;rh&quot;; Format = F(6, 0.0);    Validator = Validator.Float } // Create some text generators let gen1 = new TextGenerator( [| &quot;20110410 66.34 1019.3 27.00&quot; &quot;20110411 73.12 1064.2 48.93&quot; |]) let gen2 = new TextGenerator(     [|  &quot;This is a bad line 1&quot;         &quot;20110409   6AEGD  1014.2   32.14&quot;     |])
  • 86. let runTest gen =     let parser = new FormatParser(gen)     let workflow = parse {         let! dateT     = parser.Parse dt         let! _         = parser.Parse x1 // we don't care about X()         let! tempT     = parser.Parse t         let! _         = parser.Parse x2         let! pressureT = parser.Parse p         let! _         = parser.Parse x3         let! relhumT   = parser.Parse rh         let date, temperature, pressure, relhum = dateT |> gs, tempT |> gf, pressureT |> gf, relhumT |> gf         let tp = temperature * pressure         return (date, temperature, pressure, relhum, tp)         }     let result = ParseRunner.Run workflow     match result with     | ParseSuccess(d,t,p,r,tp) ->         printfn &quot;Success: Weather on %s: Temp: %f, Pres: %f, RH: %f&quot;  d t p r      | ParseFailure(msg, pos) ->         printfn &quot;Failure: %s at line %d, pos %d&quot; msg pos.Line pos.Column let runSuccess() = runTest gen1 let runFailure() = runTest gen2
  • 87. <ul><li>F# Websharper vs. Scala Lift: DSL/Functional based dynamic web application platforms </li></ul>
  • 88. <ul><li>From Anton Tayanovskyy, http://www.intellifactory.com/blogs/anton.tayanovskyy/2009/12/8/WebSharper---Write-F!sharp!-and-Run-JavaScript.article </li></ul>[<JavaScriptType>] module Math = /// Find the sum of all the multiples of 3 or 5 below 1000. [<JavaScript>] let ProjectEuler0001 = seq { 0 .. 999 } |> Seq.filter (fun x -> x % 3 = 0 || x % 5 = 0) |> Seq.sum [<JavaScriptType>] type Example() = inherit Web.Control() [<JavaScript>] override this.Body = let answer = Span [] Div [ Div [ Span [&quot;The answer is: &quot;] answer ] Input [Type &quot;Button&quot;; Value &quot;Calculate&quot;] |> On Events.Click (fun _ -> answer.Text <- string Math.ProjectEuler0001) ]
  • 89. <ul><li>Converts ProjectEuler0001() function into JavaScript </li></ul><ul><li>DSL for creating HTML/CSS layout with Ajax </li></ul><ul><li>Event handling similar to Reactive Extensions </li></ul><ul><li>Full support for RPC calls back to server-side F# </li></ul><ul><li>They've implemented most Seq.XXX functions in JavaScript </li></ul><ul><li>You can create your own F# to JavaScript functionality </li></ul>
  • 90. <ul><li>F# does not really have this feature </li></ul><ul><li>Might get around it with &quot;function injection&quot; plus default function values </li></ul>
  • 91. <ul><li>F#: Visual Studio (or SharpDevelop on Mono). F# is an official member of VS as of 2010. Pretty good Intellisense etc. Difficulties: no refactoring support. No “folder” support, have to do it manually. Certain code gen/tooling things don’t really work so often have to make C# project as a shell, then delegate much of work to F# library. Of course can always use text editor, emacs, vi and run F# compiler </li></ul><ul><li>Scala Eclipse etc. Still needs work, though Martin Odersky is apparently working fulltime on this at the moment – perhaps major improvements in 2011? IntelliJ, emacs, vi, etc. </li></ul><ul><li>F#: WPF, Silverlight, WP7, XNA, Xbox 360, WinForms, ASP.NET/MVC, SQL Server, Azure. Via Mono: Support for iPhone (Monotouch), Android (Monodroid). CouchDB (see Daniel Mohl examples). Mac/Linux support via Mono. </li></ul><ul><li>Scala: Android? Lift, integration with Java web and other frameworks </li></ul>
  • 92. <ul><li>Can use text editor/compiler for either </li></ul><ul><li>F#: Visual Studio, MSBuild, FAKE, Nant </li></ul><ul><li>Unit testing </li></ul><ul><li>F#: NUnit, FsUnit, xUnit plus some F# BDD frameworks </li></ul><ul><li>Both F# and Scala are Open Source </li></ul><ul><li>F#: Apache 2.0 license, see http://blogs.msdn.com/b/dsyme/archive/2010/11/04/announcing-the-f-compiler-library-source-code-drop.aspx </li></ul>
  • 93. <ul><li>F#: finance (Credit Suisse, etc.) </li></ul><ul><li>Machine intelligence </li></ul><ul><li>Seem to be mostly in NYC and London </li></ul><ul><li>Bing analytics </li></ul><ul><li>Xbox. New Xbox GO game </li></ul><ul><li>Many people (for example FSUG attendees) using F# for prototypes, utilities, etc. </li></ul><ul><li>See http://blogs.msdn.com/b/dsyme/ for some examples </li></ul><ul><li>Still, searching for F# in Monster, Dice, Indeed in Boston area in 2011: no hits other than Matlab </li></ul>
  • 94. <ul><li>Expert F# - Don Syme, et al </li></ul><ul><li>Real World Functional Programming – Tomas Petricek </li></ul><ul><li>Professional F# - Ted Neward, Aaron Erickson, Talbott Crowell, Rick Minerich (Talbott and Rick are current/former FSUG group leads) </li></ul><ul><li>Programming F# - Chris Smith (F# team member, now at Google) </li></ul><ul><li>Jon Harrop – F# for Technical Computing, etc. </li></ul><ul><li>Don Syme (http://blogs.msdn.com/b/dsyme) </li></ul><ul><li>Rick Minerich's &quot;F# Central&quot; (http:// fsharpcentral.com) </li></ul><ul><li>Planet F# (http://feeds.feedburner.com/planet_fsharp) </li></ul><ul><li>Tomas Petricek (http://tomasp.net/blog/) </li></ul><ul><li>Tales from a Trading Desk (M. Davey) ( http://mdavey.wordpress.com ) </li></ul><ul><li>Many, many more! </li></ul>
  • 95. <ul><li>Oldest F# user group – over 2 years old </li></ul><ul><li>http://fsug.org </li></ul><ul><li>Twitter: @fsug </li></ul><ul><li>LinkedIn: http://bit.ly/9BH5J </li></ul><ul><li>We meet first or second Monday of every month, usually at Microsoft NERD Center in Cambridge, MA </li></ul><ul><li>Next meeting Monday May 2 6:30pm at Microsoft Waltham office, 201 Jones Rd., Sixth Floor, Waltham, MA </li></ul><ul><li>Rick Minerich speaking: &quot;Numbers, Functions and Computation Expressions&quot; </li></ul><ul><li>&quot;Functional Friday&quot; – FSUG and BASE looking for speakers re functional programming. Planning a seminar in October timeframe. If interested, contact [email_address] or me at scott at fsug dot org </li></ul>
  • 96.  

×