SlideShare une entreprise Scribd logo
1  sur  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]
 

Contenu connexe

Tendances (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
 

En vedette

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
 

En vedette (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
 

Similaire à F# Intro for Scala Developers

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
 

Similaire à F# Intro for Scala Developers (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
 

Dernier

AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontologyjohnbeverley2021
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityWSO2
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Zilliz
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 

Dernier (20)

AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 

F# Intro for Scala Developers

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