F# Intro for Scala Developers
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

F# Intro for Scala Developers

on

  • 5,383 views

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.

Statistics

Views

Total Views
5,383
Views on SlideShare
5,362
Embed Views
21

Actions

Likes
3
Downloads
31
Comments
1

2 Embeds 21

http://paper.li 20
http://twitter.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • Slides 11-20 have an 'Oops! This slide did not convert properly hence cannot be displayed'
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

F# Intro for Scala Developers Presentation 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.
    • 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.
    • We’ll look at
      • Points of Intersection
      • Points of Difference
      • Points of View
  • 3.
    • Hybrid OO/Functional approach
    • Pragmatic approach
    • Seamless integration with rich existing ecosystems (.NET, JVM)
    • More or less based on previous languages (F# :: Ocaml, Scala :: Java, other influences such as Python, Ruby)
    • Listed below are 30+ features they have in common
    • "A Language that Grows on You" – both very extensible, many core features are in fact not built-in to the language
  • 4.
    • Important differences in approach, syntax, features
    • Very distinct personalities to both languages
  • 5.
    • Emerging out of rich traditions
    • Elegant approaches to modern problems
  • 6.
    • Beginnings in C/C++. Hints of functional in the STL, OO patterns
    • Java arrives on scene – so much less painful than C++: garbage collection, half the lines of code, etc.
    • C# – exciting new Java-like language but better for writing Windows-based applications
    • C# 3.0 and LINQ – lots of functional constructs (delegates, closures, lambdas, LINQ)
    • 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#
    • Java the language (NOT the ecosystem) has stagnated – Scala offers an exciting way forward
  • 7.
    • Statically typed, strongly typed
    • Type inference
    • Succinct, elegant syntax
    • Combination of those 3 make both F# and Scala “feel” like dynamic languages (e.g. Python, Ruby), but have full benefit of static typing
    • Mixed/hybrid paradigm: OO and Functional
    • Target major platforms, leverage existing ecosystems: F#: .NET CLR/Mono, use C# libraries; Scala: JVM and some .NET, use Java libraries
    • Generics
    • Operators
    • Pattern Matching
    • Immutability
    • Recursion
    • Tail-call optimization
  • 8.
    • Option, Some and None
    • Classes, interfaces, abstract classes, try/catch/finally/exceptions
    • lazy support, infinite sequences
    • Constructors where parameters become auto-generated fields/properties
    • Array/list/sequence comprehensions, yield
    • Functional data structures: Lists, Maps
    • Tuples
    • Lambda functions, higher order functions
    • Virtual and overridden methods
    • Closures
    • Map, filter, fold, reduce and friends
    • Partial function application/currying
    • Reflection – uses underlying .NET or Java reflection plus add unique features
    • Point-free style
    • Annotations/metadata – use underlying .NET and Java support
    • REPL
    • Auto-documentation
    • DSLs
  • 9.
    • Don Syme, primary creator of F#, was main force behind .NET generics. Anders Hejlsberg, lead architect of C#, was lead architect of Pascal.
    • 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
  • 10.
    • 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.).
    • Syntax differences: F# is whitespace significant
    • Scala has more sophisticated/complex type system: traits, variance, higher kinded
    • F# supports static methods but not explicit singletons (like Scala object)
    • Scala embedded XML – though F# can use DSL or leverage XLINQ
    • Visibility – F# has no protected, only internal; Scala has more options
    • F# philosophy is to de-emphasize OO, object hierarchies while still supporting it (plus interoperability with .NET). Scala embraces OO wholeheartedly and expands it
    • F# function composition, etc.
  • 11.
    • F# Pipelining, function composition vs. Fluent Interface
    • F# Discriminated Unions (difference?) vs. Scala case classes
    • F# Mailbox Processor vs. Scala Actors
    • F# Modules vs. Scala import and Predef – ability to have short functions in code with qualifying them as in C#/Java static methods
    • DSL support
    • F# WebSharper vs. Scala Lift: DSL/Functional based dynamic web application platforms, generate JavaScript
    • F# Object Expressions
    • Scala traits/mixins
    • F# Active Patterns
    • F# Units of Measure
    • F# Workflows / Computational Expressions (Monads)
    • F# async workflows
    • F# Reactive Extensions
  • 12.
    • F# values are immutable by default, you have to add mutable if desired
    • “ let” binding is immutable, similar to Scala “val”
    • “ let mutable” binding is mutable, similar to Scala “var”
    • Use <- operator instead of = for assignment
    // 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.
    • Statically typed – all the benefits of static typing
    • However, lightweight syntax and type inference make them &quot;feel&quot; in practice much closer to dynamically typed languages like Python, Ruby, JavaScript
    • F# actually even more strongly typed than C# - for example explicit conversions needed (int -> float, object -> interface)
    • However Hindley-Milner type inference makes F# extremely succinct, often very few type annotations needed
  • 14.
    • C# 2.0 is about where Java 6 is – have to explicitly declare everything
    • 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.
    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.
    • C# 3.0 has lambda expressions – but need to be explicit about types
    • C# 3.0 with generics is awash in angle brackets and type annotations.
    • C# 4.0 has tuples, but clunky and no pattern matching
    • Can't have generic type parameters to Func<> delegates – must be class members
    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.
    • C# 3.0 can also do this – method signature
    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.
    • But look at F#! No type annotations needed at all
    • Can be a class member or just nested function
    • No angle bracket mess
    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.
    • Scala: Still need to add type annotations, though syntax cleaner than C#
    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.
    • Somewhat contrived example, but power of F# type inference
    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.
    • Without inline keyword, function may be less generic than desired
    • If inline keyword used, compiler auto-generates generic constraint, then inserts function inline everywhere the function is called based on current context
    // 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.
    • Mixed paradigm: OO and Functional
    • However, F# is much more focused on Functional
    • Scala has more sophisticated OO system
    • F# has:
    • Classes
    • Structs (value types)
    • Interfaces
    • Abstract base classes
    • Object expressions
    • Single inheritance, but multiple inheritance of interfaces
    • Nothing quite like Scala Traits
    • Conversions are explicit – for example you must cast an object to an interface to use the interface-specific methods
    • F# discourages the use of deep inheritance hierarchies, opting for more functional approach
    • F# does not have protected members – only private, public, internal
  • 24.
    • F# tends to de-emphasize lots of OO
    • Record types – lightweight data structure similar to Scala case classes
    • Can also contain lambdas
    // 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.
    • F# tends to de-emphasize lots of OO
    • Record types – lightweight data structure similar to Scala case classes
    • Can also contain lambdas/function values – this can be an effective technique similar to DI
    // 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.
    • Constructors where parameters become auto-generated fields/properties
    // 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.
    • Lightweight, powerful approach instead of OO
    • &quot;Discriminators&quot; could also be function values
    • This example also shows &quot;typedef&quot;-style declarations
    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.
    • Pattern matching on Discriminated Unions
    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.
    • More pattern matching + function keyword
    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.
    • Here we combine different kinds of weather with information specific to that weather type, including units of measure specific to that type of weather
    [<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.
    • Mixed paradigm: OO and Functional
    • However, F# is much more focused on Functional
    • Scala has more sophisticated OO system
    // 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.
    • Classes
    // 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.
    • Classes, Interface casting, Object Expressions
    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.
    • Abstract Base Class
    // 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.
    • Abstract Base Class Inheritance
    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.
    • Target major platforms, leverage existing ecosystems: F#: .NET CLR/Mono, use C# libraries; Scala: JVM and some .NET, use Java libraries
    • This helps drive adoption vs. some other functional languages
  • 37.
    • F# has good support for generics including constraints
    • F# 2.0 does not have variance indicators (i.e. unlike Scala [+T] [-T])
    // 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.
    • F# has good support for generics including constraints
    • F# 2.0 does not have variance indicators (i.e. unlike Scala [+T] [-T])
    // 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.
    • Great support in F# for operator definition, very nice syntax
    • Makes it easy to define &quot;local&quot; operators
    • Some examples throughout presentation
    let (!!) a b = (a + 2) * b !! 1 2 val it : int = 6
  • 40.
    • F# has great support
    • See Discriminated Unions
    • See Active Patterns below – F#-specific feature
  • 41.
    • Tail call optimization
    • F# support this both through the compiler and CLR. The compiler transforms tail recursive call into while loops, etc.
    • The 64 bit CLR jitter can perform TCO from the raw IL. So C# code running on 64 bit may get TCO
    • JVM does not support TCO
    • Scala compiler performs TCO in some (many?) cases
    • Scala 2.8 adds the @tailrec annotation which emits a warning if scalac cannot optimize
  • 42.
    • Example of various things discussed so far
    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.
    • Pipelining operator defined as:
    [ 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.
    • Pipelining
    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
    • “ Point-free” style:
  • 47.
    • Function composition operator defined as:
    // 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.
    • Map, filter, fold, reduce and friends
    • 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
    [ 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.
    • Partial function application/currying – example above also using function composition
  • 51.
    • Reflection – F# uses underlying .NET reflection, very powerful
    • Nice pattern matching syntax, also works with Exceptions
    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.
    • Point-free style – examples shown throughout presentation
  • 53.
    • Annotations/metadata – use underlying .NET and Java support
  • 54.
    • REPL: F# Interactive
    • Part of Visual Studio or standalone console
  • 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
    • .NET XML document generation
    • In addition to C#-style comments, F# adds shortcut if just ///
    • Lots more tags than shown here
  • 56.
    • Somewhat similar to Scala Actors
    • See code for full example
    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.
    • See code example
    // 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.
    • See code example
    // 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.
    • See code example
    /// 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.
    • See code example
         /// 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.
    • F# great language for DSLs
    • Discriminated Unions, operators, combinators, whitespace, &quot;``&quot;
    • Example by Dmitri Nesteruk, http://www.codeproject.com/KB/dotnet/dslfsharp.aspx
    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.
    • Another example – NaturalSpec by Navision (Steffen Forkmann et al)
    • BDD unit testing framework
    • ' is a legal F# identifier
    • `` allows spaces inside legal F# identifiers
    [<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.
    • Yet another BDD example – FsUnit open source unit test framework (fsunit.codeplex.com)
    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.
    • Nice helper which looks like it’s accessing a property but really performs a function based on a string
    • Saves a bit of typing plus you can add some error handling in definition
    • Caveat: May fail at runtime, not compile time
    • This example is WPF/Silverlight/XAML related
    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.
    • Modules allow you to write static functions then call them without Class-Dot syntax (like you would in C# or Java)
    • Great for “operator-like” functions
    • One of those nice little things in F# that add up and make code more succinct and elegant
    • Scala Predef, apply can perform similar function
    [<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))
    • Functional way of handling events – canonical example is GUI but many other uses
    • You can perform filter, map, partition, scan, etc.
    • You can also &quot;publish&quot; events and expose them as properties in a class that others can subscribe to, plus trigger events
  • 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)
    • Functional way of handling events – canonical example is GUI but many other uses, e.g. pub/sub
    • You can perform filter, map, partition, scan, etc.
    • You can also &quot;publish&quot; events and expose them as properties in a class that others can subscribe to, plus trigger events
  • 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
    • Simple example of pub/sub – account with &quot;auditors&quot;
  • 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()
    • Continued example of pub/sub – account with &quot;auditors&quot;
  • 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 ])
    • In simplest form, allow you to take synchronous workflows and convert to async with minimal effort
    • Adapted from Don Syme
    • http://blogs.msdn.com/b/dsyme/archive/2007/10/11/introducing-f-asynchronous-workflows.aspx
  • 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
    • Example doing network I/O, here's the synchronous version
  • 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
    • Network I/O, async version
    • Results not scientific but real (dual-core PC)
  • 82.
    • This just scratches the surface of what you can do
    • Waiting, cancellation, continuations, much more
    • One case of a more general feature – workflows aka Computational Expressions
  • 83.
    • No functional language would be complete without Monads!
    • F# has excellent support
    • See http://www.synqotik.net/blog/post/2011/01/23/Understanding-F-Workflows.aspx for my example
    /// 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.
    • Continued…
    /// 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.
    • Continued…
    // 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.
    • F# Websharper vs. Scala Lift: DSL/Functional based dynamic web application platforms
  • 88.
    • From Anton Tayanovskyy, http://www.intellifactory.com/blogs/anton.tayanovskyy/2009/12/8/WebSharper---Write-F!sharp!-and-Run-JavaScript.article
    [<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.
    • Converts ProjectEuler0001() function into JavaScript
    • DSL for creating HTML/CSS layout with Ajax
    • Event handling similar to Reactive Extensions
    • Full support for RPC calls back to server-side F#
    • They've implemented most Seq.XXX functions in JavaScript
    • You can create your own F# to JavaScript functionality
  • 90.
    • F# does not really have this feature
    • Might get around it with &quot;function injection&quot; plus default function values
  • 91.
    • 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
    • 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.
    • 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.
    • Scala: Android? Lift, integration with Java web and other frameworks
  • 92.
    • Can use text editor/compiler for either
    • F#: Visual Studio, MSBuild, FAKE, Nant
    • Unit testing
    • F#: NUnit, FsUnit, xUnit plus some F# BDD frameworks
    • Both F# and Scala are Open Source
    • 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
  • 93.
    • F#: finance (Credit Suisse, etc.)
    • Machine intelligence
    • Seem to be mostly in NYC and London
    • Bing analytics
    • Xbox. New Xbox GO game
    • Many people (for example FSUG attendees) using F# for prototypes, utilities, etc.
    • See http://blogs.msdn.com/b/dsyme/ for some examples
    • Still, searching for F# in Monster, Dice, Indeed in Boston area in 2011: no hits other than Matlab
  • 94.
    • Expert F# - Don Syme, et al
    • Real World Functional Programming – Tomas Petricek
    • Professional F# - Ted Neward, Aaron Erickson, Talbott Crowell, Rick Minerich (Talbott and Rick are current/former FSUG group leads)
    • Programming F# - Chris Smith (F# team member, now at Google)
    • Jon Harrop – F# for Technical Computing, etc.
    • Don Syme (http://blogs.msdn.com/b/dsyme)
    • Rick Minerich's &quot;F# Central&quot; (http:// fsharpcentral.com)
    • Planet F# (http://feeds.feedburner.com/planet_fsharp)
    • Tomas Petricek (http://tomasp.net/blog/)
    • Tales from a Trading Desk (M. Davey) ( http://mdavey.wordpress.com )
    • Many, many more!
  • 95.
    • Oldest F# user group – over 2 years old
    • http://fsug.org
    • Twitter: @fsug
    • LinkedIn: http://bit.ly/9BH5J
    • We meet first or second Monday of every month, usually at Microsoft NERD Center in Cambridge, MA
    • Next meeting Monday May 2 6:30pm at Microsoft Waltham office, 201 Jones Rd., Sixth Floor, Waltham, MA
    • Rick Minerich speaking: &quot;Numbers, Functions and Computation Expressions&quot;
    • &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
  • 96.