f# intro for scala developers

96
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

Upload: fsug

Post on 18-Dec-2014

5.183 views

Category:

Technology


1 download

DESCRIPTION

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

TRANSCRIPT

Page 1: F# Intro for Scala Developers

Boston Area Scala Enthusiasts, April 11th, 2011 • Microsoft NERD • Cambridge, MA

let talk = things |> Seq.filter (fsharp >> cool) |> Seq.map scala |> Seq.take n

let talk = things |> Seq.filter (fsharp >> cool) |> Seq.map scala |> Seq.take n

Page 2: F# Intro for Scala Developers

• 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

Page 3: F# Intro for Scala Developers

• 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

Page 4: F# Intro for Scala Developers

• Important differences in approach, syntax, features• Very distinct personalities to both languages

Page 5: F# Intro for Scala Developers

• Emerging out of rich traditions• Elegant approaches to modern problems

Page 6: F# Intro for Scala Developers

• 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

Page 7: F# Intro for Scala Developers

• 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

Page 8: F# Intro for Scala Developers

• 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

Page 9: F# Intro for Scala Developers

• 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

Page 10: F# Intro for Scala Developers

• 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.

Page 11: F# Intro for Scala Developers

• 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

Page 12: F# Intro for Scala Developers

• 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 = 42let mutable m = 100a <- 10 // won't compilem <- 101 // OKa = 100 // OK, but it's a boolean expression!

// Scalaval a = 42var m = 100

// F#let a = 42let mutable m = 100a <- 10 // won't compilem <- 101 // OKa = 100 // OK, but it's a boolean expression!

// Scalaval a = 42var m = 100

Page 13: F# Intro for Scala Developers

• Statically typed – all the benefits of static typing

• However, lightweight syntax and type inference make them "feel" 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

Page 14: F# Intro for Scala Developers

• 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>();Dictionary<string,int> dict = new Dictionary<string,int>();

C# 2.0/Java 6

var dict = new Dictionary<string,int>();var dict = new Dictionary<string,int>();

C# 3.0

let dict = Dictionary<string,int>()let dict = Dictionary<string,int>()

F#

Page 15: F# Intro for Scala Developers

• 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); }};

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!

Page 16: F# Intro for Scala Developers

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, "Hello");var tInt = t.Item1;var tString = t.Item2;

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, "Hello");var tInt = t.Item1;var tString = t.Item2;

Page 17: F# Intro for Scala Developers

• 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); } }}

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

Page 18: F# Intro for Scala Developers

C# 3.0/4.0 – a lot better than Java, but still not a full functional language

“ Mads Torgersen, C# Product Managerhttp://blogs.msdn.com/b/madst/archive/2007/01/23/is-c-becoming-a-functional-language.aspx

“ Mads Torgersen, C# Product Managerhttp://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.

Page 19: F# Intro for Scala Developers

• 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); } }}

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

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#

Page 20: F# Intro for Scala Developers

• 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

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) }}

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

Page 21: F# Intro for Scala Developers

• 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));};

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

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)}

def f[T,U,V] (g : (T) => U, h : (U, U) => V, a : T, b : T) : V = { h(g a, g b)}

Scala

Page 22: F# Intro for Scala Developers

• 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 genericlet 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

// No inline keyword – not genericlet 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

Page 23: F# Intro for Scala Developers

• 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

Page 24: F# Intro for Scala Developers

• 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# recordtype CarRecord = { Make : string Model : string Year : int Color : string }

let m3 = { Make = "BMW"; Model = "M3"; Year = 2011; Color = "MetallicPebbleGray" }

let m5 = { m3 with Model = "M5"; Color = "Crimson" }

// Scala:case class Car(make:String, model:String, year:Int, Color:String);

// Car as an F# recordtype CarRecord = { Make : string Model : string Year : int Color : string }

let m3 = { Make = "BMW"; Model = "M3"; Year = 2011; Color = "MetallicPebbleGray" }

let m5 = { m3 with Model = "M5"; Color = "Crimson" }

// Scala:case class Car(make:String, model:String, year:Int, Color:String);

Page 25: F# Intro for Scala Developers

• 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 drivetype MovingCar = { Make : string Model : string Year : int Color : string Drive : unit -> unit }

let m3 = { Make = "BMW"; Model = "M3"; Year = 2011; Color = "MetallicPebbleGray"; Drive = fun () -> printfn("Vroom" }

let m5 = { m3 with Model = "M5"; Color = "Crimson"; Drive = fun () -> printfn "Vroom VROOM!!" }

// MovingCar is an F# record that can drivetype MovingCar = { Make : string Model : string Year : int Color : string Drive : unit -> unit }

let m3 = { Make = "BMW"; Model = "M3"; Year = 2011; Color = "MetallicPebbleGray"; Drive = fun () -> printfn("Vroom" }

let m5 = { m3 with Model = "M5"; Color = "Crimson"; Drive = fun () -> printfn "Vroom VROOM!!" }

Page 26: F# Intro for Scala Developers

• Constructors where parameters become auto-generated fields/properties// Car as an F# type (.NET class)// Doesn't compile - "make" 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

// Car as an F# type (.NET class)// Doesn't compile - "make" 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

Page 27: F# Intro for Scala Developers

• Lightweight, powerful approach instead of OO• "Discriminators" could also be function values• This example also shows "typedef"-style declarations

type Make = stringtype Model = stringtype TrainLine = Orange | Red | Green | Purple | Silvertype Route = int

type Transport =| Car of Make * Model| Train of TrainLine| Bicycle| Bus of Route| Walking

let alice = Car("BMW", "M5")let bob = Train(Orange)let carol = Bicyclelet dave = Bus(42)let peggy = Walking

type Make = stringtype Model = stringtype TrainLine = Orange | Red | Green | Purple | Silvertype Route = int

type Transport =| Car of Make * Model| Train of TrainLine| Bicycle| Bus of Route| Walking

let alice = Car("BMW", "M5")let bob = Train(Orange)let carol = Bicyclelet dave = Bus(42)let peggy = Walking

Page 28: F# Intro for Scala Developers

• Pattern matching on Discriminated Unions

let averageSpeed (t : Transport) = match tr with | Car(make,model) when make = "BMW" -> 90 | Car _ -> 55 | Bicycle -> 18 | Bus _ -> 24 | Train(r) -> match r with | Orange | Red -> 28 | Green -> 13 | Purple -> 45 | Silver -> 18 | Walking -> 5

let averageSpeed (t : Transport) = match tr with | Car(make,model) when make = "BMW" -> 90 | Car _ -> 55 | Bicycle -> 18 | Bus _ -> 24 | Train(r) -> match r with | Orange | Red -> 28 | Green -> 13 | Purple -> 45 | Silver -> 18 | Walking -> 5

Page 29: F# Intro for Scala Developers

• More pattern matching + function keyword

let averageSpeed = function | Car(make,model) when make = "BMW" -> 90 | Car _ -> 55 ...

let f = function ...

// same aslet f x = match x with | ...

let averageSpeed = function | Car(make,model) when make = "BMW" -> 90 | Car _ -> 55 ...

let f = function ...

// same aslet f x = match x with | ...

Page 30: F# Intro for Scala Developers

• 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!

[<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!

Page 31: F# Intro for Scala Developers

• 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 "traits" 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

// Interface -// this is inferred due to all properties/methods being abstract// Note, cannot have "traits" 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

Page 32: F# Intro for Scala Developers

• Classes

// Classtype BaseAnimal(name, talk, move) =    let mutable age = 0

    // "do" expressions - part of constructor    do printfn "Constructing animal %s who says %s" name talk

    // alternate constructor    new(name) = BaseAnimal(name, "Hello", "Walk")        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 "%s" talk        member x.Move() = printfn "%s" move

// Deriving from base typetype Owl(name) = inherit BaseAnimal(name, "Scrreeech", "Swoooop")type Turkey(name) = inherit BaseAnimal(name, "Gobble gobble", "Flap flap")

// Classtype BaseAnimal(name, talk, move) =    let mutable age = 0

    // "do" expressions - part of constructor    do printfn "Constructing animal %s who says %s" name talk

    // alternate constructor    new(name) = BaseAnimal(name, "Hello", "Walk")        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 "%s" talk        member x.Move() = printfn "%s" move

// Deriving from base typetype Owl(name) = inherit BaseAnimal(name, "Scrreeech", "Swoooop")type Turkey(name) = inherit BaseAnimal(name, "Gobble gobble", "Flap flap")

Page 33: F# Intro for Scala Developers

• Classes, Interface casting, Object Expressions

let chicken =  BaseAnimal("Henery",     "Bwock bwock bwock", "Shuffle shuffle")let moose   = BaseAnimal("Bullwinkle", "Dum de dum",        "Loaf shuffle loaf")

// Have to cast to IAnimal!// moose.Talk() - won't compilelet imoose = moose :> IAnimalimoose.Talk()imoose.Move()

// Object expression - define interface "inline"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 "Neigh"        member x.Move() = printfn "Gallop" }

let quickDraw = horse("McGraw")quickDraw.Age <- 10

let chicken =  BaseAnimal("Henery",     "Bwock bwock bwock", "Shuffle shuffle")let moose   = BaseAnimal("Bullwinkle", "Dum de dum",        "Loaf shuffle loaf")

// Have to cast to IAnimal!// moose.Talk() - won't compilelet imoose = moose :> IAnimalimoose.Talk()imoose.Move()

// Object expression - define interface "inline"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 "Neigh"        member x.Move() = printfn "Gallop" }

let quickDraw = horse("McGraw")quickDraw.Age <- 10

Page 34: F# Intro for Scala Developers

• 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[<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()

Page 35: F# Intro for Scala Developers

• Abstract Base Class Inheritance

type Eagle(title, name) =    inherit AbstractBird(name)

    override this.Name with get() = title + " " + name    override x.Talk() = printfn "Arrrrr"    override x.Fly()  = printfn "Swoop"

let e = Eagle("Lord", "Gwaihir")// Don't have to cast to IAnimale.Talk()e.Fly()

// IAnimal can Move() but not Fly()let ie = e :> IAnimalie.Move()// ie.Fly() - won't compile

type Eagle(title, name) =    inherit AbstractBird(name)

    override this.Name with get() = title + " " + name    override x.Talk() = printfn "Arrrrr"    override x.Fly()  = printfn "Swoop"

let e = Eagle("Lord", "Gwaihir")// Don't have to cast to IAnimale.Talk()e.Fly()

// IAnimal can Move() but not Fly()let ie = e :> IAnimalie.Move()// ie.Fly() - won't compile

Page 36: F# Intro for Scala Developers

• 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

Page 37: F# Intro for Scala Developers

• 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 constraintstype 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 parameterlet f = Filter<_>(42)let res1 = f.Equals(2)

// Built in generic constraintstype 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 parameterlet f = Filter<_>(42)let res1 = f.Equals(2)

Page 38: F# Intro for Scala Developers

• 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 constraintstype 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 <- slet b = Base("Base")let d = Derived("Derived")setName b "NewBase"setName d "NewDerived"

// User defined generic constraintstype 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 <- slet b = Base("Base")let d = Derived("Derived")setName b "NewBase"setName d "NewDerived"

Page 39: F# Intro for Scala Developers

• Great support in F# for operator definition, very nice syntax• Makes it easy to define "local" operators• Some examples throughout presentation

let (!!) a b = (a + 2) * b

!! 1 2 val it : int = 6

let (!!) a b = (a + 2) * b

!! 1 2 val it : int = 6

Page 40: F# Intro for Scala Developers

• F# has great support• See Discriminated Unions• See Active Patterns below – F#-specific feature

Page 41: F# Intro for Scala Developers

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

Page 42: F# Intro for Scala Developers

• 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 numberslet myColors = [ "Red"; "Green"; "Blue"; "Purple"; "Orange" ]let addStrings (s0 : string) (s1 : string) = System.String.Join(", ", [| s0; s1 |])

let sumOfColors = sum2 addStrings "" myColors

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 numberslet myColors = [ "Red"; "Green"; "Blue"; "Purple"; "Orange" ]let addStrings (s0 : string) (s1 : string) = System.String.Join(", ", [| s0; s1 |])

let sumOfColors = sum2 addStrings "" myColors

Page 43: F# Intro for Scala Developers

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 = "Spain"; Cities = ["Barcelona"; "Madrid" ] } { Name = "Germany"; Cities = ["Berlin"; "Frankfurt" ] } { Name = "USA"; Cities = ["Boston"; "New York ] } { Name = "India"; Cities = ["Bhopal"; "Mumbai" ] } ]

let populations : IDictionary<string,long> = ...

let mySeq = seq { for c in countries do for city in c.Cities do if city.StartsWith("b") then let pop = populations.["city"] yield city, country, pop }

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 = "Spain"; Cities = ["Barcelona"; "Madrid" ] } { Name = "Germany"; Cities = ["Berlin"; "Frankfurt" ] } { Name = "USA"; Cities = ["Boston"; "New York ] } { Name = "India"; Cities = ["Bhopal"; "Mumbai" ] } ]

let populations : IDictionary<string,long> = ...

let mySeq = seq { for c in countries do for city in c.Cities do if city.StartsWith("b") then let pop = populations.["city"] yield city, country, pop }

Page 44: F# Intro for Scala Developers

mySeq|> Seq.filter (fun (_,_,pop) -> pop > 1000000)|> Seq.sortBy (fun (_,_,pop) -> -pop) // descending|> Seq.map (fun (city,c,pop) -> sprintf "%s, %s. Pop.: %d" city c pop)

mySeq|> Seq.filter (fun (_,_,pop) -> pop > 1000000)|> Seq.sortBy (fun (_,_,pop) -> -pop) // descending|> Seq.map (fun (city,c,pop) -> sprintf "%s, %s. Pop.: %d" city c pop)

Page 45: F# Intro for Scala Developers

• 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 ]

[ 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 xlet (|>) x f = f x

Page 46: F# Intro for Scala Developers

• 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 "Value: %d" x)

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 "Value: %d" x)

let isEven x = x % 2 = 0let pv x = printfn "Value: %d" x

[| 1; 2; 3; 4; 5 |]|> Array.partition isEven|> fst|> Array.map (( * ) 2)|> Array.filter ((<) 4) // backwards, i.e. 4 < x|> Array.iter pv

let isEven x = x % 2 = 0let pv x = printfn "Value: %d" 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:

Page 47: F# Intro for Scala Developers

• Function composition operator defined as:

// inline need else F# will assume intslet inline square a = a * alet inline multiply a b = a * blet inline add a b = a + blet add10 = add 10let mult7 = multiply 7let g = square >> add10 >> mult7let squaredPlus10 = [ 1; 2; 3; 4; 5 ] |> List.map g

let addFloat = add 123.456let multiPi = multiply 3.14159let h = square >> addFloat >> multiPilet items = [ 1.1; 2.2; 3.3; 4.4; 5.5 ] |> List.map h

// inline need else F# will assume intslet inline square a = a * alet inline multiply a b = a * blet inline add a b = a + blet add10 = add 10let mult7 = multiply 7let g = square >> add10 >> mult7let squaredPlus10 = [ 1; 2; 3; 4; 5 ] |> List.map g

let addFloat = add 123.456let multiPi = multiply 3.14159let h = square >> addFloat >> multiPilet items = [ 1.1; 2.2; 3.3; 4.4; 5.5 ] |> List.map h

let (>>) f g x = g(f(x))let (>>) f g x = g(f(x))

Page 48: F# Intro for Scala Developers

• 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)

[ "one"; "two"; "three"; "four"; "five" ]|> List.map (fun s -> s.ToUpperCase())|> List.reduce (fun acc elem -> acc + ", " + elem)

[ 1; 2; 3; 4; 5 ]|> List.map (( * ) 2)|> List.reduce (fun acc elem -> acc + elem)

[ "one"; "two"; "three"; "four"; "five" ]|> List.map (fun s -> s.ToUpperCase())|> List.reduce (fun acc elem -> acc + ", " + elem)

Page 49: F# Intro for Scala Developers

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 = [ "one"; "two"; "three"; "four"; "five" ]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'; ...]

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 = [ "one"; "two"; "three"; "four"; "five" ]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'; ...]

Page 50: F# Intro for Scala Developers

• Partial function application/currying – example above also using function composition

Page 51: F# Intro for Scala Developers

• 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 "It's a triangle"| :? Circle c -> printfn "Circle with radius %f" c.Radius| :? Rectangle r -> printfn "Rectangle of area %f" r.Width * r.Length| _ -> failwith "Unknown shape!"

try failingOperation()with| :? IOException ioex -> printfn "IO Problem: %s" ioex.Message| :? NullReferenceException _ -> printfn "Billion dollar problem!"| exn -> printfn "Some unknown problem: %s" exn.Message

type IShape() = ... // interface

match getShape() with| :? Triangle t -> printfn "It's a triangle"| :? Circle c -> printfn "Circle with radius %f" c.Radius| :? Rectangle r -> printfn "Rectangle of area %f" r.Width * r.Length| _ -> failwith "Unknown shape!"

try failingOperation()with| :? IOException ioex -> printfn "IO Problem: %s" ioex.Message| :? NullReferenceException _ -> printfn "Billion dollar problem!"| exn -> printfn "Some unknown problem: %s" exn.Message

Page 52: F# Intro for Scala Developers

• Point-free style – examples shown throughout presentation

Page 53: F# Intro for Scala Developers

• Annotations/metadata – use underlying .NET and Java support

Page 54: F# Intro for Scala Developers

• REPL: F# Interactive• Part of Visual Studio or standalone console

Page 55: F# Intro for Scala Developers

/// 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="i0">The first number</param> /// <param name="i1">The second number</param> member x.Add(i0, i1) = i0 + i1

/// 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="i0">The first number</param> /// <param name="i1">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

Page 56: F# Intro for Scala Developers

• 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 -> "Success"    | Failure(s) -> "Failure: " + s

type AuditMessage = { ID : Ticket; AccountName : string; Action : string; Amount : decimal; Date : DateTime; Result : AccountResult }    with member x.AsString with get() =  sprintf "ID: %d, Account: %s, Action: %s, Amount: %M, Date: %A, Result: %s"x.ID x.AccountName x.Action x.Amount x.Date (x.Result |> res2String)

open System

type Ticket = int64

type AccountResult =| Success| Failure of string

let res2String = function    | Success -> "Success"    | Failure(s) -> "Failure: " + s

type AuditMessage = { ID : Ticket; AccountName : string; Action : string; Amount : decimal; Date : DateTime; Result : AccountResult }    with member x.AsString with get() =  sprintf "ID: %d, Account: %s, Action: %s, Amount: %M, Date: %A, Result: %s"x.ID x.AccountName x.Action x.Amount x.Date (x.Result |> res2String)

Page 57: F# Intro for Scala Developers

• See code example

// Packets within the MailboxProcessortype 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 syntaxtype MessageRequest =| EchoRequest of string| AuditReportRequestMsg| DepositRequest of string * decimal| WithdrawalRequest of string * string * decimal| MessageCountRequest| StopRequest

type Reply =| ReplyString of string| ReplyMessage of AuditMessage

// Packets within the MailboxProcessortype 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 syntaxtype MessageRequest =| EchoRequest of string| AuditReportRequestMsg| DepositRequest of string * decimal| WithdrawalRequest of string * string * decimal| MessageCountRequest| StopRequest

type Reply =| ReplyString of string| ReplyMessage of AuditMessage

Page 58: F# Intro for Scala Developers

• See code example

// Convert Reply to inner valuelet getReply = function  ReplyString(s) -> s | ReplyMessage(msg) -> msg.AsStringlet getMsg   = function ReplyMessage(msg) -> msg | _ -> failwith "Only call getMsg when expecting a ReplyMessage"

/// Our highly sophisticated, iron-clad, thread-unsafe bank accounttype 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("Insufficient funds!")        else            balance <- balance - amount            Success

// Convert Reply to inner valuelet getReply = function  ReplyString(s) -> s | ReplyMessage(msg) -> msg.AsStringlet getMsg   = function ReplyMessage(msg) -> msg | _ -> failwith "Only call getMsg when expecting a ReplyMessage"

/// Our highly sophisticated, iron-clad, thread-unsafe bank accounttype 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("Insufficient funds!")        else            balance <- balance - amount            Success

Page 59: F# Intro for Scala Developers

• See code example

/// Agent that wraps a MailboxProcessor "workflow" 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

/// Agent that wraps a MailboxProcessor "workflow" 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

Page 60: F# Intro for Scala Developers

• See code example

    /// Create a report from the audit messages    let createReport() =        let arr =             auditMessages            |> List.rev            |> List.map (fun a -> sprintf "[%A] Account %s: %s of $%M %s" a.Date a.AccountName a.Action a.Amount (res2String a.Result))            |> Array.ofSeq        "AUDIT: " + System.String.Join("\r\n", arr)

    /// Create a report from the audit messages    let createReport() =        let arr =             auditMessages            |> List.rev            |> List.map (fun a -> sprintf "[%A] Account %s: %s of $%M %s" a.Date a.AccountName a.Action a.Amount (res2String a.Result))            |> Array.ofSeq        "AUDIT: " + System.String.Join("\r\n", arr)

Page 61: F# Intro for Scala Developers

    /// 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 - 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)

Page 62: F# Intro for Scala Developers

    /// 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("ECHO: " + 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                | Echo(echo, channel) ->                    channel.Reply("ECHO: " + echo)                    return! loop (ticket + 1L)                | AuditReportRequest(channel) ->                    channel.Reply(createReport())                    return! loop (ticket + 1L)                | NumMessages(channel) ->                    channel.Reply(n)                    return! loop (ticket + 1L)

Page 63: F# Intro for Scala Developers

    /// 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, "Deposit", amt, Success)                        channel.Reply(msg)                    else                        let msg = addMsg 

(t, name, "Deposit", amt, Failure("Account " + name + " not found"))

                        channel.Reply(msg)                    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, "Deposit", amt, Success)                        channel.Reply(msg)                    else                        let msg = addMsg 

(t, name, "Deposit", amt, Failure("Account " + name + " not found"))

                        channel.Reply(msg)                    return! loop (ticket + 1L)

Page 64: F# Intro for Scala Developers

// Scala style syntax helper - almostlet (<!) (a : AccountAgent) (req : MessageRequest) = a.SendMessage req

let agent = new AccountAgent(bankAccounts)

let s = agent.Echo("Hello world!")let mutable n = agent.MessageCount()printfn "Messages: %d" nprintfn "Making deposits..."agent <! DepositRequest("Alice", 1200M) |> ignoreagent <! DepositRequest("Bob",  200M)  |> ignoreagent <! DepositRequest("Carol", 300M)  |> ignoreagent <! DepositRequest("Dave",  400M)  |> ignore

n <- agent <! MessageCountRequest |> getReply |> int64printfn "Messages: %d" n

// Scala style syntax helper - almostlet (<!) (a : AccountAgent) (req : MessageRequest) = a.SendMessage req

let agent = new AccountAgent(bankAccounts)

let s = agent.Echo("Hello world!")let mutable n = agent.MessageCount()printfn "Messages: %d" nprintfn "Making deposits..."agent <! DepositRequest("Alice", 1200M) |> ignoreagent <! DepositRequest("Bob",  200M)  |> ignoreagent <! DepositRequest("Carol", 300M)  |> ignoreagent <! DepositRequest("Dave",  400M)  |> ignore

n <- agent <! MessageCountRequest |> getReply |> int64printfn "Messages: %d" n

Page 65: F# Intro for Scala Developers

• F# great language for DSLs• Discriminated Unions, operators, combinators, whitespace, "``"• Example by Dmitri Nesteruk, http://www.codeproject.com/KB/dotnet/dslfsharp.aspx

project "F# DSL Article" starts "01/01/2009"resource "Dmitri" isa "Writer" with_rate 140resource "Computer" isa "Dumb Machine" with_rate 0group "DSL Popularization" done_by "Dmitri"task "Create basic estimation DSL" takes 1 daytask "Write article" takes 1 day task"Post article and wait for comments" takes 1 weekgroup "Infrastructure Support" done_by "Computer"task "Provide VS2010 and MS Project" takes 1 daytask "Download and deploy TypograFix" takes 1 daytask "Sit idly while owner waits for comments" takes 1 weekprepare my_project

project "F# DSL Article" starts "01/01/2009"resource "Dmitri" isa "Writer" with_rate 140resource "Computer" isa "Dumb Machine" with_rate 0group "DSL Popularization" done_by "Dmitri"task "Create basic estimation DSL" takes 1 daytask "Write article" takes 1 day task"Post article and wait for comments" takes 1 weekgroup "Infrastructure Support" done_by "Computer"task "Provide VS2010 and MS Project" takes 1 daytask "Download and deploy TypograFix" takes 1 daytask "Sit idly while owner waits for comments" takes 1 weekprepare my_project

Page 66: F# Intro for Scala Developers

• 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]                 // "Arrange" test context    |> When removing 3              // "Act"    |> It shouldn't contain 3       // "Assert"    |> 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

[<Scenario>]let ``When removing an element from a list it should not contain the element``() =  Given [1;2;3;4;5]                 // "Arrange" test context    |> When removing 3              // "Act"    |> It shouldn't contain 3       // "Assert"    |> 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

Page 67: F# Intro for Scala Developers

• Yet another BDD example – FsUnit open source unit test framework (fsunit.codeplex.com)

true |> should be Truefalse |> should not (be True)[] |> should be Empty[1] |> should not (be Empty)

(fun () -> failwith "BOOM!" |> ignore) |> should throw typeof<System.Exception>

type LightBulb(state) = member x.On = state override x.ToString() = match x.On with | true -> "On" | false -> "Off"

[<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 "On".`` ()= string lightBulb |> should equal "On"

true |> should be Truefalse |> should not (be True)[] |> should be Empty[1] |> should not (be Empty)

(fun () -> failwith "BOOM!" |> ignore) |> should throw typeof<System.Exception>

type LightBulb(state) = member x.On = state override x.ToString() = match x.On with | true -> "On" | false -> "Off"

[<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 "On".`` ()= string lightBulb |> should equal "On"

Page 68: F# Intro for Scala Developers

// Simple Active Pattern – returns a booleanlet (|UpperChar|) c = Char.ToUpper(c)

// Partial Active Pattern – Some (with possible transformation)// or Nonelet (|IsDigit|_|) c = if Char.IsDigit(c) then Some(int c) // convert char to an int else None

// Active Pattern with parameters + reusing above APslet (|IsDigitInRange|_|) rangeStart rangeEnd c = match c with | IsDigit(n) -> if n >= rangeStart && n <= rangeEnd then Some(n) else None | _ -> None

// Simple Active Pattern – returns a booleanlet (|UpperChar|) c = Char.ToUpper(c)

// Partial Active Pattern – Some (with possible transformation)// or Nonelet (|IsDigit|_|) c = if Char.IsDigit(c) then Some(int c) // convert char to an int else None

// Active Pattern with parameters + reusing above APslet (|IsDigitInRange|_|) rangeStart rangeEnd c = match c with | IsDigit(n) -> if n >= rangeStart && n <= rangeEnd then Some(n) else None | _ -> None

Page 69: F# Intro for Scala Developers

// Partial Active Patternlet (|Match|_|) (regex : Regex) input =    if regex.IsMatch(input) then        Some(regex.Match(input))    else None

// Active pattern -// "partitions" input into one of several "classes"let (|Zip|Country|State|City|Invalid|) s =  match s with | Match regexZip m     -> Zip(m |> result "zip", "", "", "") | Match regexCity m -> City("",resCountry m,resState m,m |> result "city") | Match regexState m  -> State("", resCountry m, resState m, "") | Match regexCountry m -> Country("", resCountry m, "", "") | _                    -> Invalid

// Partial Active Patternlet (|Match|_|) (regex : Regex) input =    if regex.IsMatch(input) then        Some(regex.Match(input))    else None

// Active pattern -// "partitions" input into one of several "classes"let (|Zip|Country|State|City|Invalid|) s =  match s with | Match regexZip m     -> Zip(m |> result "zip", "", "", "") | Match regexCity m -> City("",resCountry m,resState m,m |> result "city") | Match regexState m  -> State("", resCountry m, resState m, "") | Match regexCountry m -> Country("", resCountry m, "", "") | _                    -> Invalid

Page 70: F# Intro for Scala Developers

// Using Active Pattern, this is simplifiedlet parse input = match input with | Zip(z, _, _, _)     -> { Country = ""; State = ""; City = ""; Zip = z } | Country(_, c, _, _) -> { Country = c;  State = ""; City = ""; Zip = "" } | State(_, c, s, _)   -> { Country = c;  State = s;  City = ""; Zip = "" } | City(_, co, st, ci) -> { Country = co; State = st; City = ci; Zip = "" } | Invalid             -> { Country = ""; State = ""; City = ""; Zip = "" }

// Using Active Pattern, this is simplifiedlet parse input = match input with | Zip(z, _, _, _)     -> { Country = ""; State = ""; City = ""; Zip = z } | Country(_, c, _, _) -> { Country = c;  State = ""; City = ""; Zip = "" } | State(_, c, s, _)   -> { Country = c;  State = s;  City = ""; Zip = "" } | City(_, co, st, ci) -> { Country = co; State = st; City = ci; Zip = "" } | Invalid             -> { Country = ""; State = ""; City = ""; Zip = "" }

Page 71: F# Intro for Scala Developers

// Partial Active Pattern - returns Option. If Some(_) then returns a LocationInfolet (|ValidLocation|_|) input =    match input with    | Zip(z, _, _, _)     -> Some({ Country = ""; State = ""; City = ""; Zip = z })    | City(_, co, st, ci) -> Some({ Country = co; State = st; City = ci; Zip = "" })    | _                   -> None

// Is this a "valid" location?// Use of "function"let parseIsValid = function    | ValidLocation(loc) -> true    | _                  -> false

// Same as...let parseIsValid2 input =     match input with    | ValidLocation(loc) -> true    | _                  -> false

// Partial Active Pattern - returns Option. If Some(_) then returns a LocationInfolet (|ValidLocation|_|) input =    match input with    | Zip(z, _, _, _)     -> Some({ Country = ""; State = ""; City = ""; Zip = z })    | City(_, co, st, ci) -> Some({ Country = co; State = st; City = ci; Zip = "" })    | _                   -> None

// Is this a "valid" location?// Use of "function"let parseIsValid = function    | ValidLocation(loc) -> true    | _                  -> false

// Same as...let parseIsValid2 input =     match input with    | ValidLocation(loc) -> true    | _                  -> false

Page 72: F# Intro for Scala Developers

// 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 "0%d" i ]

    match input with    | HasZip bostonZips z -> 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 "0%d" i ]

    match input with    | HasZip bostonZips z -> true    | _                   -> false

    

Page 73: F# Intro for Scala Developers

• 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("ic") :?> ItemsControl

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("ic") :?> ItemsControl

Page 74: F# Intro for Scala Developers

• 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

[<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

Page 75: F# Intro for Scala Developers

open System.Drawingopen System.Windows.Formslet form = new Form(Text = "F# Windows Form",                    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 "line segments" between clicksform.MouseMove    |> Event.filter (fun evArgs -> rect.Contains(evArgs.X, evArgs.Y))    |> Event.pairwise    |> Event.add (fun (ev1,ev2) -> lineSegments.Add(ev1.Location, ev2.Location))

open System.Drawingopen System.Windows.Formslet form = new Form(Text = "F# Windows Form",                    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 "line segments" between clicksform.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 "publish" events and expose them as properties in a class that others can subscribe to, plus trigger events

Page 76: F# Intro for Scala Developers

// 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 clickedlet 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 "Left mouse clicked at (%d,%d) at %A" evArgs.X evArgs.Y DateTime.Now)|> Event.add (fun s -> form.Text <- s; form.BackColor <- Color.Lime)

buttonLeft|> Event.map (fun evArgs -> sprintf "Right mouse clicked at (%d,%d) at %A" evArgs.X evArgs.Y DateTime.Now)|> Event.add (fun s -> form.Text <- s; form.BackColor <- Color.Red)

// 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 clickedlet 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 "Left mouse clicked at (%d,%d) at %A" evArgs.X evArgs.Y DateTime.Now)|> Event.add (fun s -> form.Text <- s; form.BackColor <- Color.Lime)

buttonLeft|> Event.map (fun evArgs -> sprintf "Right mouse clicked at (%d,%d) at %A" 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 "publish" events and expose them as properties in a class that others can subscribe to, plus trigger events

Page 77: F# Intro for Scala Developers

[<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 "%s of $%d at %A" s amt DateTime.Now        this.NotifyAction(msg)        member x.Deposit amount =        balance <- balance + amount        notify "Deposit" amount

    member x.Withdraw amount =        if amount > balance then            notify "ERROR Withdrawal attempt" amount        else            balance <- balance - amount            notify "Withdrawal" amount

[<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 "%s of $%d at %A" s amt DateTime.Now        this.NotifyAction(msg)        member x.Deposit amount =        balance <- balance + amount        notify "Deposit" amount

    member x.Withdraw amount =        if amount > balance then            notify "ERROR Withdrawal attempt" amount        else            balance <- balance - amount            notify "Withdrawal" amount

• Simple example of pub/sub – account with "auditors"

Page 78: F# Intro for Scala Developers

type Auditor(name) =    let messages = new ResizeArray<string>()

    let messageReceived s =         messages.Add(s)        printfn "%s received: %s" name s

    member x.MessageReceived s = messageReceived s

let execute() =    let account = Account(1000)    let auditor1 = Auditor("Auditor 1")    let auditor2 = Auditor("Auditor 2")    account.PropertyChanged |> Event.add (fun s -> auditor1.MessageReceived(s))    account.PropertyChanged        |> Event.filter (fun s -> s.StartsWith("ERROR"))        |> Event.add (fun s -> auditor2.MessageReceived(s))

    account.Deposit(500)    account.Withdraw(700)    account.Withdraw(4000)

execute()

type Auditor(name) =    let messages = new ResizeArray<string>()

    let messageReceived s =         messages.Add(s)        printfn "%s received: %s" name s

    member x.MessageReceived s = messageReceived s

let execute() =    let account = Account(1000)    let auditor1 = Auditor("Auditor 1")    let auditor2 = Auditor("Auditor 2")    account.PropertyChanged |> Event.add (fun s -> auditor1.MessageReceived(s))    account.PropertyChanged        |> Event.filter (fun s -> s.StartsWith("ERROR"))        |> Event.add (fun s -> auditor2.MessageReceived(s))

    account.Deposit(500)    account.Withdraw(700)    account.Withdraw(4000)

execute()

• Continued example of pub/sub – account with "auditors"

Page 79: F# Intro for Scala Developers

// 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 ])

// 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

Page 80: F# Intro for Scala Developers

// Adapted from http://msdn.microsoft.com/en-us/library/dd233250.aspx#Y267

let urlList = [ "Microsoft.com", "http://www.microsoft.com/"                "MSDN", "http://msdn.microsoft.com/"                "Bing", "http://www.bing.com"              ]

let fetchSync(name, url:string) =    try        printfn "Getting %s..." name        let uri = new System.Uri(url)        let webClient = new WebClient()        let html = webClient.DownloadString(uri)        printfn "Read %d characters for %s" html.Length name    with        | ex -> printfn "%s" (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

// Adapted from http://msdn.microsoft.com/en-us/library/dd233250.aspx#Y267

let urlList = [ "Microsoft.com", "http://www.microsoft.com/"                "MSDN", "http://msdn.microsoft.com/"                "Bing", "http://www.bing.com"              ]

let fetchSync(name, url:string) =    try        printfn "Getting %s..." name        let uri = new System.Uri(url)        let webClient = new WebClient()        let html = webClient.DownloadString(uri)        printfn "Read %d characters for %s" html.Length name    with        | ex -> printfn "%s" (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

Page 81: F# Intro for Scala Developers

let fetchAsync(name, url:string) =    async {         try            let uri = new System.Uri(url)            let webClient = new WebClient()            let! html = webClient.AsyncDownloadString(uri)            printfn "Read %d characters for %s" html.Length name        with            | ex -> printfn "%s" (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

let fetchAsync(name, url:string) =    async {         try            let uri = new System.Uri(url)            let webClient = new WebClient()            let! html = webClient.AsyncDownloadString(uri)            printfn "Read %d characters for %s" html.Length name        with            | ex -> printfn "%s" (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)

Page 82: F# Intro for Scala Developers

• 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

Page 83: F# Intro for Scala Developers

• 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 occurredtype ParseResult<'T> =| ParseSuccess of 'T| ParseFailure of string * Position

/// The "monadic type"type ParseInfo<'T> = (unit -> ParseResult<'T>)

/// Workflow utilitieslet 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 vlet zeroM () = failM "" { Line = 0; Column = 0 }let delayM f = (fun () -> runM (f()))

/// 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 occurredtype ParseResult<'T> =| ParseSuccess of 'T| ParseFailure of string * Position

/// The "monadic type"type ParseInfo<'T> = (unit -> ParseResult<'T>)

/// Workflow utilitieslet 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 vlet zeroM () = failM "" { Line = 0; Column = 0 }let delayM f = (fun () -> runM (f()))

Page 84: F# Intro for Scala Developers

• 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 { } syntaxlet parse = new ParseBuilder()

/// 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 { } syntaxlet parse = new ParseBuilder()

Page 85: F# Intro for Scala Developers

• Continued…

// Create some format specifierslet dateValidator = Validator.Regex(@"[1-9][0-9]{3}[0-1][0-9][0-3][0-9]")

let  dt = { Name = "date";   Format = A(8, "");  Validator = dateValidator }let  x1 = { Name = "_x1";       Format = X(2);   Validator = Validator.True }let  t = { Name = "tempF"; Format = F(6, 0.0);  Validator = Validator.Float }let  x2 = { Name = "_x2";       Format = X(2);   Validator = Validator.True }let  p = { Name = "pressure"; Format = F(6, 0.0); Validator = Validator.Float } let  x3 = { Name = "_x3";       Format = X(2);   Validator = Validator.True }let  rh = { Name = "rh"; Format = F(6, 0.0);    Validator = Validator.Float }

// Create some text generatorslet gen1 = new TextGenerator( [| "20110410 66.34 1019.3 27.00" "20110411 73.12 1064.2 48.93" |])

let gen2 = new TextGenerator(    [|  "This is a bad line 1"        "20110409   6AEGD  1014.2   32.14"    |])

// Create some format specifierslet dateValidator = Validator.Regex(@"[1-9][0-9]{3}[0-1][0-9][0-3][0-9]")

let  dt = { Name = "date";   Format = A(8, "");  Validator = dateValidator }let  x1 = { Name = "_x1";       Format = X(2);   Validator = Validator.True }let  t = { Name = "tempF"; Format = F(6, 0.0);  Validator = Validator.Float }let  x2 = { Name = "_x2";       Format = X(2);   Validator = Validator.True }let  p = { Name = "pressure"; Format = F(6, 0.0); Validator = Validator.Float } let  x3 = { Name = "_x3";       Format = X(2);   Validator = Validator.True }let  rh = { Name = "rh"; Format = F(6, 0.0);    Validator = Validator.Float }

// Create some text generatorslet gen1 = new TextGenerator( [| "20110410 66.34 1019.3 27.00" "20110411 73.12 1064.2 48.93" |])

let gen2 = new TextGenerator(    [|  "This is a bad line 1"        "20110409   6AEGD  1014.2   32.14"    |])

Page 86: F# Intro for Scala Developers

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 "Success: Weather on %s: Temp: %f, Pres: %f, RH: %f"  d t p r    | ParseFailure(msg, pos) ->        printfn "Failure: %s at line %d, pos %d" msg pos.Line pos.Column

let runSuccess() = runTest gen1let runFailure() = runTest gen2

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 "Success: Weather on %s: Temp: %f, Pres: %f, RH: %f"  d t p r    | ParseFailure(msg, pos) ->        printfn "Failure: %s at line %d, pos %d" msg pos.Line pos.Column

let runSuccess() = runTest gen1let runFailure() = runTest gen2

Page 87: F# Intro for Scala Developers

• F# Websharper vs. Scala Lift: DSL/Functional based dynamic web application platforms

Page 88: F# Intro for Scala Developers

• 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 ["The answer is: "] answer ]

Input [Type "Button"; Value "Calculate"] |> On Events.Click (fun _ -> answer.Text <- string Math.ProjectEuler0001) ]

[<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 ["The answer is: "] answer ]

Input [Type "Button"; Value "Calculate"] |> On Events.Click (fun _ -> answer.Text <- string Math.ProjectEuler0001) ]

Page 89: F# Intro for Scala Developers

• 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

Page 90: F# Intro for Scala Developers

• F# does not really have this feature• Might get around it with "function injection" plus default function values

Page 91: F# Intro for Scala Developers

• 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

Page 92: F# Intro for Scala Developers

• 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

Page 93: F# Intro for Scala Developers

• 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

Page 94: F# Intro for Scala Developers

• 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 "F# Central" (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!

Page 95: F# Intro for Scala Developers

• 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: "Numbers, Functions and Computation Expressions"

• "Functional Friday" – FSUG and BASE looking for speakers re functional programming. Planning a seminar in October timeframe. If interested, contact [email protected] or me at scott at fsug dot org

Page 96: F# Intro for Scala Developers