SlideShare una empresa de Scribd logo
1 de 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
[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object]
[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],// 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
[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],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#
[object Object],[object Object],[object Object],[object Object],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;
[object Object],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.
[object Object],[object Object],[object Object],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#
[object Object],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
[object Object],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
[object Object],[object Object],// 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
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],// 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);
[object Object],[object Object],[object Object],// 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; }
[object Object],// 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
[object Object],[object Object],[object Object],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
[object Object],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
[object Object],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 | ...
[object Object],[<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!
[object Object],[object Object],[object Object],// 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
[object Object],// 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;)
[object Object],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
[object Object],// 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()
[object Object],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
[object Object],[object Object]
[object Object],[object Object],// 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)
[object Object],[object Object],// 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;
[object Object],[object Object],[object Object],let (!!) a b = (a + 2) * b !! 1 2 val it : int = 6
[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],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)
[object Object],[ 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
[object Object],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 ,[object Object]
[object Object],// 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))
[object Object],[object Object],[ 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'; ...]
[object Object]
[object Object],[object Object],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
[object Object]
[object Object]
[object Object],[object Object]
/// 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 ,[object Object],[object Object],[object Object]
[object Object],[object Object],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)
[object Object],// 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
[object Object],// 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
[object Object],/// 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
[object Object],     /// 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;&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
[object Object],[object Object],[object Object],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
[object Object],[object Object],[object Object],[object Object],[<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
[object Object],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     
[object Object],[object Object],[object Object],[object Object],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
[object Object],[object Object],[object Object],[object Object],[<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)) ,[object Object],[object Object],[object Object]
// 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) ,[object Object],[object Object],[object Object]
[<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 ,[object Object]
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() ,[object Object]
// 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 ]) ,[object Object],[object Object],[object Object]
// 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 ,[object Object]
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 ,[object Object],[object Object]
[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],/// 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()))
[object Object],/// 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()
[object Object],// 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
[object Object]
[object Object],[<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) ]
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
 

Más contenido relacionado

La actualidad más candente (20)

Introduction to F#
Introduction to F#Introduction to F#
Introduction to F#
 
Introduction to F# 3.0
Introduction to F# 3.0Introduction to F# 3.0
Introduction to F# 3.0
 
Python Introduction
Python IntroductionPython Introduction
Python Introduction
 
Lecture 04 syntax analysis
Lecture 04 syntax analysisLecture 04 syntax analysis
Lecture 04 syntax analysis
 
Syntax analysis
Syntax analysisSyntax analysis
Syntax analysis
 
Parsing
ParsingParsing
Parsing
 
Report on c and c++
Report on c and c++Report on c and c++
Report on c and c++
 
Parsing
ParsingParsing
Parsing
 
Pcd question bank
Pcd question bank Pcd question bank
Pcd question bank
 
Lexical analyzer
Lexical analyzerLexical analyzer
Lexical analyzer
 
Syntax directed translation
Syntax directed translationSyntax directed translation
Syntax directed translation
 
Lecture 13 intermediate code generation 2.pptx
Lecture 13 intermediate code generation 2.pptxLecture 13 intermediate code generation 2.pptx
Lecture 13 intermediate code generation 2.pptx
 
Syntax Analysis in Compiler Design
Syntax Analysis in Compiler Design Syntax Analysis in Compiler Design
Syntax Analysis in Compiler Design
 
Advanced C Language for Engineering
Advanced C Language for EngineeringAdvanced C Language for Engineering
Advanced C Language for Engineering
 
Lexical
LexicalLexical
Lexical
 
Types of Parser
Types of ParserTypes of Parser
Types of Parser
 
Syntax analyzer
Syntax analyzerSyntax analyzer
Syntax analyzer
 
Compiler design syntax analysis
Compiler design syntax analysisCompiler design syntax analysis
Compiler design syntax analysis
 
Parsing
ParsingParsing
Parsing
 
Basic C Programming language
Basic C Programming languageBasic C Programming language
Basic C Programming language
 

Destacado

No health without_mental_health_-_framework_july_2012
No health without_mental_health_-_framework_july_2012No health without_mental_health_-_framework_july_2012
No health without_mental_health_-_framework_july_2012José Galrinho
 
Syllabaus, Suny It Course, New Media, Draft 3, 23 August20091
Syllabaus, Suny It Course, New Media, Draft 3, 23 August20091Syllabaus, Suny It Course, New Media, Draft 3, 23 August20091
Syllabaus, Suny It Course, New Media, Draft 3, 23 August20091Nick Jankowski
 
Jankowski, ALPSP conference, Enhanced Journal Article, 11Sept.2009
Jankowski, ALPSP conference, Enhanced Journal Article, 11Sept.2009Jankowski, ALPSP conference, Enhanced Journal Article, 11Sept.2009
Jankowski, ALPSP conference, Enhanced Journal Article, 11Sept.2009Nick Jankowski
 
Primary School Italy
Primary School ItalyPrimary School Italy
Primary School ItalyHERETER
 

Destacado (8)

CALIDAD EN HOTELES
CALIDAD EN HOTELESCALIDAD EN HOTELES
CALIDAD EN HOTELES
 
No health without_mental_health_-_framework_july_2012
No health without_mental_health_-_framework_july_2012No health without_mental_health_-_framework_july_2012
No health without_mental_health_-_framework_july_2012
 
Non drug management of diabetesPPT
Non drug management of diabetesPPTNon drug management of diabetesPPT
Non drug management of diabetesPPT
 
Syllabaus, Suny It Course, New Media, Draft 3, 23 August20091
Syllabaus, Suny It Course, New Media, Draft 3, 23 August20091Syllabaus, Suny It Course, New Media, Draft 3, 23 August20091
Syllabaus, Suny It Course, New Media, Draft 3, 23 August20091
 
Non drug management of diabetes
Non drug management of diabetesNon drug management of diabetes
Non drug management of diabetes
 
Non drug management of diabetes
Non drug management of diabetesNon drug management of diabetes
Non drug management of diabetes
 
Jankowski, ALPSP conference, Enhanced Journal Article, 11Sept.2009
Jankowski, ALPSP conference, Enhanced Journal Article, 11Sept.2009Jankowski, ALPSP conference, Enhanced Journal Article, 11Sept.2009
Jankowski, ALPSP conference, Enhanced Journal Article, 11Sept.2009
 
Primary School Italy
Primary School ItalyPrimary School Italy
Primary School Italy
 

Similar a Boston Scala and F# Meetup Discusses Hybrid Functional Languages

Qcon2011 functions rockpresentation_f_sharp
Qcon2011 functions rockpresentation_f_sharpQcon2011 functions rockpresentation_f_sharp
Qcon2011 functions rockpresentation_f_sharpMichael Stal
 
Qcon2011 functions rockpresentation_f_sharp
Qcon2011 functions rockpresentation_f_sharpQcon2011 functions rockpresentation_f_sharp
Qcon2011 functions rockpresentation_f_sharpMichael Stal
 
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Martin Odersky
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to ScalaSynesso
 
About Functional Programming
About Functional ProgrammingAbout Functional Programming
About Functional ProgrammingAapo Kyrölä
 
Functional programming is the most extreme programming
Functional programming is the most extreme programmingFunctional programming is the most extreme programming
Functional programming is the most extreme programmingsamthemonad
 
Haskell retrospective
Haskell retrospectiveHaskell retrospective
Haskell retrospectivechenge2k
 
ParaSail
ParaSail  ParaSail
ParaSail AdaCore
 
Scala intro for Java devs 20150324
Scala intro for Java devs 20150324Scala intro for Java devs 20150324
Scala intro for Java devs 20150324Erik Schmiegelow
 
Master in javascript
Master in javascriptMaster in javascript
Master in javascriptRobbin Zhao
 
Scala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationScala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationMartin Odersky
 
Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...
Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...
Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...Raffi Khatchadourian
 

Similar a Boston Scala and F# Meetup Discusses Hybrid Functional Languages (20)

F# 101
F# 101F# 101
F# 101
 
Qcon2011 functions rockpresentation_f_sharp
Qcon2011 functions rockpresentation_f_sharpQcon2011 functions rockpresentation_f_sharp
Qcon2011 functions rockpresentation_f_sharp
 
Qcon2011 functions rockpresentation_f_sharp
Qcon2011 functions rockpresentation_f_sharpQcon2011 functions rockpresentation_f_sharp
Qcon2011 functions rockpresentation_f_sharp
 
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009
 
Swift, swiftly
Swift, swiftlySwift, swiftly
Swift, swiftly
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
Andy On Closures
Andy On ClosuresAndy On Closures
Andy On Closures
 
About Functional Programming
About Functional ProgrammingAbout Functional Programming
About Functional Programming
 
Functional programming is the most extreme programming
Functional programming is the most extreme programmingFunctional programming is the most extreme programming
Functional programming is the most extreme programming
 
Introduction to es6
Introduction to es6Introduction to es6
Introduction to es6
 
Haskell retrospective
Haskell retrospectiveHaskell retrospective
Haskell retrospective
 
ParaSail
ParaSail  ParaSail
ParaSail
 
F# for Scala developers
F# for Scala developersF# for Scala developers
F# for Scala developers
 
Scala intro for Java devs 20150324
Scala intro for Java devs 20150324Scala intro for Java devs 20150324
Scala intro for Java devs 20150324
 
Master in javascript
Master in javascriptMaster in javascript
Master in javascript
 
Scala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationScala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentation
 
Intro to Scala
 Intro to Scala Intro to Scala
Intro to Scala
 
Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...
Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...
Open Problems in Automatically Refactoring Legacy Java Software to use New Fe...
 
F# Tutorial @ QCon
F# Tutorial @ QConF# Tutorial @ QCon
F# Tutorial @ QCon
 
python and perl
python and perlpython and perl
python and perl
 

Último

The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 

Último (20)

The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 

Boston Scala and F# Meetup Discusses Hybrid Functional Languages

  • 1. Boston Area Scala Enthusiasts, April 11 th , 2011 • Microsoft NERD • Cambridge, MA let talk = things |> Seq.filter (fsharp >> cool) |> Seq.map scala |> Seq.take n
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16. C# 3.0 – can do this Func<Func<int,string,bool>, Func<int,string,Tuple<int,string>>,int,string, Tuple<int,string>> filtermap = (f, m, a, b) => { if (f(a,b)) { return m(a,b); } else { return Tuple.Create(a, b); } }; Func<int,string,bool> filter = ...; Func<int,string,Tuple<int,string>> map = ...; var t = filtermap(filter, map, 1, &quot;Hello&quot;); var tInt = t.Item1; var tString = t.Item2;
  • 17.
  • 18. C# 3.0/4.0 – a lot better than Java, but still not a full functional language “ Mads Torgersen, C# Product Manager http://blogs.msdn.com/b/madst/archive/2007/01/23/is-c-becoming-a-functional-language.aspx People who are functional programmers by night and have to write C# by day will find that the daily headache sets in a little later in the afternoon.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43. let arr = [| 1; 2; 3; 4; 5 |] let list = [ for i in 0 .. 2 .. 24 -> i * 4 ] type Country = { Name : string; Cities: string seq } let countries = [ { Name = &quot;Spain&quot;; Cities = [&quot;Barcelona&quot;; &quot;Madrid&quot; ] } { Name = &quot;Germany&quot;; Cities = [&quot;Berlin&quot;; &quot;Frankfurt&quot; ] } { Name = &quot;USA&quot;; Cities = [&quot;Boston&quot;; &quot;New York ] } { Name = &quot;India&quot;; Cities = [&quot;Bhopal&quot;; &quot;Mumbai&quot; ] } ] let populations : IDictionary<string,long> = ... let mySeq = seq { for c in countries do for city in c.Cities do if city.StartsWith(&quot;b&quot;) then let pop = populations.[&quot;city&quot;] yield city, country, pop }
  • 44. mySeq |> Seq.filter (fun (_,_,pop) -> pop > 1000000) |> Seq.sortBy (fun (_,_,pop) -> -pop) // descending |> Seq.map (fun (city,c,pop) -> sprintf &quot;%s, %s. Pop.: %d&quot; city c pop)
  • 45.
  • 46.
  • 47.
  • 48.
  • 49. let mapReduce() =     [ 1; 2; 3; 4; 5 ]     |> List.map (( * ) 2)     |> List.reduce (fun acc elem -> acc + elem) let res = mapReduce() val it : int = 30 let words = [ &quot;one&quot;; &quot;two&quot;; &quot;three&quot;; &quot;four&quot;; &quot;five&quot; ] let flatMapDistinctToUpperSorted() =     let chars =          words         |> List.map (fun w -> w.ToCharArray() |> List.ofArray)         |> Seq.ofList // Seq needed for certain functions         |> Seq.concat // flatten         |> Seq.distinct         |> Seq.map (fun c -> System.Char.ToUpper(c))         |> Seq.sort     chars let res2 = flatMapDistinctToUpperSorted() val it : seq<char> = seq ['E'; 'F'; 'H'; 'I'; ...]
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.      /// Our asynchronous agent processor - skeleton     let agent = MailboxProcessor.Start(fun inbox ->         let rec loop ticket =             async {                 let! msg = inbox.Receive()                 match msg with                 | Echo(echo, channel) -> // ...                     return! loop (ticket + 1L)                 | AuditReportRequest(channel) -> // ...                 | NumMessages(channel) -> // ...                 | Deposit(name,amt,channel) ->  // ...                     return! loop (ticket + 1L)                 | Withdrawal(name,withdrawer,amt,channel) -> // ...                     return! loop (ticket + 1L)                 | Stop -> () // stop looping             }         loop EmptyTicket)
  • 62.      /// Our asynchronous agent processor     let agent = MailboxProcessor.Start(fun inbox ->         let rec loop ticket =             async {                 let! msg = inbox.Receive()                 match msg with                 | Echo(echo, channel) ->                     channel.Reply(&quot;ECHO: &quot; + echo)                     return! loop (ticket + 1L)                 | AuditReportRequest(channel) ->                     channel.Reply(createReport())                     return! loop (ticket + 1L)                 | NumMessages(channel) ->                     channel.Reply(n)                     return! loop (ticket + 1L)
  • 63.      /// Our asynchronous agent processor     let agent = MailboxProcessor.Start(fun inbox ->         let rec loop ticket =             async {                 let! msg = inbox.Receive()                 match msg with // ...                | Deposit(name,amt,channel) ->                      let t = ticket                     if accountMap.ContainsKey(name) then                         let a = accountMap.[name]                         a.Deposit(amt) |> ignore                         let msg = addMsg (t, name, &quot;Deposit&quot;, amt, Success)                         channel.Reply(msg)                     else                         let msg = addMsg  (t, name, &quot;Deposit&quot;, amt,  Failure(&quot;Account &quot; + name + &quot; not found&quot;))                         channel.Reply(msg)                     return! loop (ticket + 1L)
  • 64. // Scala style syntax helper - almost let (<!) (a : AccountAgent) (req : MessageRequest) = a.SendMessage req let agent = new AccountAgent(bankAccounts) let s = agent.Echo(&quot;Hello world!&quot;) let mutable n = agent.MessageCount() printfn &quot;Messages: %d&quot; n printfn &quot;Making deposits...&quot; agent <! DepositRequest(&quot;Alice&quot;, 1200M) |> ignore agent <! DepositRequest(&quot;Bob&quot;,  200M)  |> ignore agent <! DepositRequest(&quot;Carol&quot;, 300M)  |> ignore agent <! DepositRequest(&quot;Dave&quot;,  400M)  |> ignore n <- agent <! MessageCountRequest |> getReply |> int64 printfn &quot;Messages: %d&quot; n
  • 65.
  • 66.
  • 67.
  • 68. // Simple Active Pattern – returns a boolean let (|UpperChar|) c = Char.ToUpper(c) // Partial Active Pattern – Some (with possible transformation) // or None let (|IsDigit|_|) c = if Char.IsDigit(c) then Some(int c) // convert char to an int else None // Active Pattern with parameters + reusing above APs let (|IsDigitInRange|_|) rangeStart rangeEnd c = match c with | IsDigit(n) -> if n >= rangeStart && n <= rangeEnd then Some(n) else None | _ -> None
  • 69. // Partial Active Pattern let (|Match|_|) (regex : Regex) input =     if regex.IsMatch(input) then         Some(regex.Match(input))     else None // Active pattern - // &quot;partitions&quot; input into one of several &quot;classes&quot; let (|Zip|Country|State|City|Invalid|) s =   match s with | Match regexZip m     -> Zip(m |> result &quot;zip&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;) | Match regexCity m -> City(&quot;&quot;,resCountry m,resState m,m |> result &quot;city&quot;) | Match regexState m  -> State(&quot;&quot;, resCountry m, resState m, &quot;&quot;) | Match regexCountry m -> Country(&quot;&quot;, resCountry m, &quot;&quot;, &quot;&quot;) | _                    -> Invalid
  • 70. // Using Active Pattern, this is simplified let parse input = match input with | Zip(z, _, _, _)     -> { Country = &quot;&quot;; State = &quot;&quot;; City = &quot;&quot;; Zip = z } | Country(_, c, _, _) -> { Country = c;  State = &quot;&quot;; City = &quot;&quot;; Zip = &quot;&quot; } | State(_, c, s, _)   -> { Country = c;  State = s;  City = &quot;&quot;; Zip = &quot;&quot; } | City(_, co, st, ci) -> { Country = co; State = st; City = ci; Zip = &quot;&quot; } | Invalid             -> { Country = &quot;&quot;; State = &quot;&quot;; City = &quot;&quot;; Zip = &quot;&quot; }
  • 71. // Partial Active Pattern - returns Option. If Some(_) then returns a LocationInfo let (|ValidLocation|_|) input =     match input with     | Zip(z, _, _, _)     -> Some({ Country = &quot;&quot;; State = &quot;&quot;; City = &quot;&quot;; Zip = z })     | City(_, co, st, ci) -> Some({ Country = co; State = st; City = ci; Zip = &quot;&quot; })     | _                   -> None // Is this a &quot;valid&quot; location? // Use of &quot;function&quot; let parseIsValid = function     | ValidLocation(loc) -> true     | _                  -> false // Same as... let parseIsValid2 input =      match input with     | ValidLocation(loc) -> true     | _                  -> false
  • 72. // Partial/Parameterized Active Pattern // Does this have a zip code contained in zipList? let (|HasZip|_|) (zipList : string list) input =     match input with     | Zip(z, _, _, _) when (zipList |> List.exists (fun x -> x = z)) -> Some(z)     //| City(_, co, st, ci)          -> None  // could do a lookup here...     | _                                                              -> None let isBoston input =     // 02101 - 02299     let bostonZips = [ for i in 2101 .. 2299 -> sprintf &quot;0%d&quot; i ]      match input with     | HasZip bostonZips z -> true     | _                   -> false     
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86. let runTest gen =     let parser = new FormatParser(gen)     let workflow = parse {         let! dateT     = parser.Parse dt         let! _         = parser.Parse x1 // we don't care about X()         let! tempT     = parser.Parse t         let! _         = parser.Parse x2         let! pressureT = parser.Parse p         let! _         = parser.Parse x3         let! relhumT   = parser.Parse rh         let date, temperature, pressure, relhum = dateT |> gs, tempT |> gf, pressureT |> gf, relhumT |> gf         let tp = temperature * pressure         return (date, temperature, pressure, relhum, tp)         }     let result = ParseRunner.Run workflow     match result with     | ParseSuccess(d,t,p,r,tp) ->         printfn &quot;Success: Weather on %s: Temp: %f, Pres: %f, RH: %f&quot;  d t p r      | ParseFailure(msg, pos) ->         printfn &quot;Failure: %s at line %d, pos %d&quot; msg pos.Line pos.Column let runSuccess() = runTest gen1 let runFailure() = runTest gen2
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.