• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
F# Intro for Scala Developers
 

F# Intro for Scala Developers

on

  • 5,043 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,043
Views on SlideShare
5,022
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

11 of 1 previous next

  • 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 F# Intro for Scala Developers Presentation Transcript

    • 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
      • 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
      • 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
      • Important differences in approach, syntax, features
      • Very distinct personalities to both languages
      • Emerging out of rich traditions
      • Elegant approaches to modern problems
      • 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
      • 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
      • 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
      • 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
      • 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.
      • 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
      • 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
      • 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
      • 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#
      • 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!
    • 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;
      • 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
    • 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.
      • 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#
      • 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
      • 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
      • 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
      • 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
      • 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);
      • 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; }
      • 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
      • 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
      • 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
      • 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 | ...
      • 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!
      • 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
      • 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;)
      • 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
      • 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()
      • 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
      • 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
      • 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)
      • 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;
      • 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
      • F# has great support
      • See Discriminated Unions
      • See Active Patterns below – F#-specific feature
      • 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
      • 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
    • 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 }
    • 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)
      • 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
      • 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:
      • 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))
      • 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)
    • 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'; ...]
      • Partial function application/currying – example above also using function composition
      • 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
      • Point-free style – examples shown throughout presentation
      • Annotations/metadata – use underlying .NET and Java support
      • REPL: F# Interactive
      • Part of Visual Studio or standalone console
    • /// 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
      • 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)
      • 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
      • 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
      • 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
      • 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)
    •      /// 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)
    •      /// 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)
    •      /// 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)
    • // 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
      • 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
      • 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
      • 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;
    • // 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
    • // 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
    • // 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; }
    • // 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
    • // 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     
      • 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
      • 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
    • 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
    • // 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
    • [<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;
    • 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;
    • // 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
    • // 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
    • 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)
      • 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
      • 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()))
      • 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()
      • 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;     |])
    • 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
      • F# Websharper vs. Scala Lift: DSL/Functional based dynamic web application platforms
      • 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) ]
      • 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
      • F# does not really have this feature
      • Might get around it with &quot;function injection&quot; plus default function values
      • 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
      • 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
      • 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
      • 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!
      • 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
    •