Taking Functional Programming into the Mainstream<br />Don Syme, <br />Principal Researcher<br />Microsoft Research, Cambr...
Disclaimer<br />I’m a Microsoft Guy. I’m a .NET Fan. I will be using Visual Studio in this talk.<br />This talk is offered...
Topics<br />Why is Microsoft Investing in Functional Programming?<br />Some Simple F# Programming<br />A Taste of Parallel...
Why is Microsoft investing in Functional Programming?<br />
What Investments?<br />C# (Generics, LINQ)<br />F#<br />Reactive Framework<br />Haskell<br />VB, Python, Ruby<br />
Simplicity<br />
Economics<br />
Fun, Fun and More Fun!<br />
Simplicity<br />
Code!<br />//F#<br />open System<br />let a = 2<br />Console.WriteLine a<br />//C#<br />using System;<br />namespace Conso...
Pleasure<br />Pain<br /> <br />type Command = Command of (Rover -&gt; unit)<br />let BreakCommand    = <br />  Command(fun...
Pleasure<br />Pain<br />let swap (x, y) = (y, x)<br />let rotations (x, y, z) = <br />    [ (x, y, z);<br />      (z, x, y...
Pleasure<br />Pain<br />type Expr =   <br />    | True   <br />    | And of Expr * Expr   <br />    | Nand of Expr * Expr ...
Economics<br />
Fun, Fun and More Fun!<br />
You<br />Can<br />Interoperate<br />With<br />Everything<br />
Everything<br />Can<br />Interoperate<br />With<br />You<br />
F#:  Influences<br />F#<br />Similar core <br />language<br />Similar object<br />model<br />
F#: Combining Paradigms<br />I&apos;ve been coding in F# lately, for a production task. F# allows you to move smoothly in ...
Let’s WebCrawl...<br />
Orthogonal & Unified Constructs<br />Let “let” simplify your life…<br />Type inference.  The safety of C# with the succinc...
Quick Tour<br />Comments <br />// comment<br />(* comment *)<br />/// XML doc comment<br />let x = 1<br />
Quick Tour<br />Overloaded Arithmetic<br />x + yAddition<br />x - ySubtraction<br />x * yMultiplication<br />x / yDivision...
Fundamentals - Whitespace Matters<br />letcomputeDeriative f x = <br />let p1 = f (x - 0.05)<br />let p2 = f (x + 0.05)<br...
Fundamentals - Whitespace Matters<br />letcomputeDeriative f x = <br />let p1 = f (x - 0.05)<br />let p2 = f (x + 0.05)<br...
Orthogonal & Unified Constructs<br />Functions: like delegates + unified and simple<br />One simple <br />mechanism, <br /...
Functional– Pipelines<br />x |&gt; f<br />The pipeline operator<br />
Functional– Pipelines<br />x |&gt; f1<br />    |&gt; f2<br />    |&gt; f3<br />Successive stages <br />in a pipeline<br />
Functional – Pipelining<br />open System.IO<br />let files =<br />Directory.GetFiles(@&quot;c:&quot;, &quot;*.*&quot;,<br ...
Immutability the norm…<br />Data is immutable by default<br />Values may not be changed<br />Copy & Update<br />Not Muta...
In Praise of Immutability<br />Immutable objects can be relied upon<br />Immutable objects can transfer between threads<br...
Functional Data – Generating Structured Data<br />Union type <br />(no data = enum)<br />type Suit =<br />    | Heart<br /...
Functional Data – Generating Structured Data (2)<br />let suits = [ Heart; Diamond; Spade; Club ]<br /> <br />letdeckOfCar...
Weakly Typed? Slow?<br />//F#<br />#light<br />open System<br />let a = 2<br />Console.WriteLine(a)<br />//C#<br />using S...
F#<br />Yet rich, dynamic<br />Yet succinct<br />
What is Functional Programming?<br />“Working with immutable data”<br />“A language with queries”<br />“A language with la...
Some Micro Trends<br />Communication With Immutable Data<br />Programming With Queries<br />Programming With Lambdas<br />...
The Huge Trends<br />THE WEB<br />MULTICORE<br />
F# Objects<br />
F# - Objects + Functional<br />type Vector2D (dx:double, dy:double) =<br />   memberv.DX = dx<br />   memberv.DY = dy<br /...
F# - Objects + Functional<br />type Vector2D(dx:double,dy:double) =<br />   let norm2 = dx*dx+dy*dy<br />   memberv.DX = d...
F# - Objects + Functional<br />typeHuffmanEncoding(freq:seq&lt;char*int&gt;) =<br />   ...<br />   &lt; 50 lines of beauti...
F# - Objects + Functional<br />type Vector2D(dx:double,dy:double) =<br />   letmutablecurrDX = dx<br />   letmutablecurrDX...
OO <br />and<br />Functional<br />Can<br />Mix<br />
Interlude: Case Study<br />
The adCenter Problem<br />
The Scale of Things<br />Weeks of data in training: <br />N,000,000,000 impressions, 6TB data<br />2 weeks of CPU time dur...
F# and adCenter<br />4 week project, 4 machine learning experts<br />100million probabilistic variables <br />Processes 6T...
AdPredict: What We Observed<br />Quick Coding<br />Agile Coding<br />Scripting<br />Performance<br />Memory-Faithful<br />...
Smooth Transitions<br />Researcher’s Brain  Realistic, Efficient Code<br />Realistic, Efficient Code  Component<br />Com...
F# Async/Parallel<br />
F# is a Parallel Language<br />(Multiple active computations)<br />F# is a Reactive Language<br />(Multiple pending reacti...
async { ... }<br />A Building Block for <br />Writing Reactive Code<br />async { ... }<br />For users:<br />   			You can ...
async { ... }<br />Asynchronous &quot;non-blocking&quot; action<br />async { let! image = ReadAsync &quot;cat.jpg&quot;<br...
Code: Web Translation<br />
Typical F# Reactive Architecture<br />Async.Start (async { ... }<br />...<br />Async.Parallel [ ... ]<br />Single Threaded...
Taming Asynchronous I/O<br />using System;<br />using System.IO;<br />using System.Threading;<br /> <br />public class Bul...
Units of Measure<br />
let EarthMass = 5.9736e24&lt;kg&gt;<br />// Average between pole and equator radii<br />let EarthRadius = 6371.0e3&lt;m&gt...
Microsoft + Eclipse Interoperability<br />For Vijay Rajagopalan<br />Microsoft Interoperability Team<br />
Announcing: Projects fostering interoperability between Eclipse and Microsoft’s platform<br />
8 Ways to Learn Functional Programming<br /><ul><li>http://cs.hubfs.net
Scala
C# 3.0
ML</li></ul>F# + FSI.exe<br />F# + Reflector<br />Haskell<br />Clojure<br />
Books about F#<br />Visit 	www.fsharp.net<br />
Books about F#<br />Visit 	www.fsharp.net<br />
Questions<br />
The many uses of async { ... }<br />Sequencing CPU computations<br />Sequencing I/O requests<br />async { let result1 = fi...
The many uses of async { ... }<br />Parallel CPU computations<br />Parallel I/O requests<br />Async.Parallel [  async { re...
The many uses of async { ... }<br />Sequencing CPU computations and I/O requests<br />async { let!lang = callDetectLanguag...
Upcoming SlideShare
Loading in...5
×

Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

2,162

Published on

Keynote from Eclipse Summit Europe 2009, presented by Don Syme from Microsoft Research.

Over the last 10 years, Microsoft Research has been able to help progress functional programming to the point that it is now an accepted mainstream approach for certain problem domains. Now, with the increasing amount of data available to us, we need new ways of thinking around how to create scalable solutions in order to best exploit it as the multi-core revolution takes hold. Languages such as F#, Scala, Erlang and Haskell are well suited to this task as their functional programming style emphasize immutability, side effect free functions, compositional parallelism and asynchronous I/O. In this talk I will use F# as an extended example of how functional programming is becoming part of the mainstream, with ramifications across the spectrum of programming languages and platforms. We will look at why Microsoft and Microsoft Research is investing in functional programming, what this has meant for F#, C# and Haskell, and what we've done to build product-quality support for F#. Note: Examples will be given using Microsoft Visual Studio, though the talk is offered in the spirit of cooperation and progress across computing platforms.

Published in: Technology, Sports
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,162
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
72
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide
  • But why does F# omit any type information? Is it not type safe? Is it coercive maybe? Or weakly typed? Maybe this is one of those dynamic languages I read about at 37 signals?
  • But it has some features to make this a little more comfortable. We’ll see a bit of that later.
  • Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

    1. 1. Taking Functional Programming into the Mainstream<br />Don Syme, <br />Principal Researcher<br />Microsoft Research, Cambridge<br />
    2. 2. Disclaimer<br />I’m a Microsoft Guy. I’m a .NET Fan. I will be using Visual Studio in this talk.<br />This talk is offered in a spirit of cooperation and idea exchange. Please accept it as such <br />
    3. 3. Topics<br />Why is Microsoft Investing in Functional Programming?<br />Some Simple F# Programming<br />A Taste of Parallel/Reactive with F#<br />An Announcement<br />
    4. 4. Why is Microsoft investing in Functional Programming?<br />
    5. 5. What Investments?<br />C# (Generics, LINQ)<br />F#<br />Reactive Framework<br />Haskell<br />VB, Python, Ruby<br />
    6. 6. Simplicity<br />
    7. 7. Economics<br />
    8. 8. Fun, Fun and More Fun!<br />
    9. 9. Simplicity<br />
    10. 10. Code!<br />//F#<br />open System<br />let a = 2<br />Console.WriteLine a<br />//C#<br />using System;<br />namespace ConsoleApplication1<br />{<br />class Program<br />{<br />static int a()<br />{<br />return 2;<br />}<br />static void Main(string[] args)<br />{<br />Console.WriteLine(a); <br />}<br />}<br />}<br />More Noise <br />Than Signal!<br />
    11. 11. Pleasure<br />Pain<br /> <br />type Command = Command of (Rover -&gt; unit)<br />let BreakCommand    = <br /> Command(fun rover -&gt; rover.Accelerate(-1.0))<br />let TurnLeftCommand = <br /> Command(fun rover -&gt; rover.Rotate(-5.0&lt;degs&gt;))<br /> <br />   abstract class Command<br />    {<br />        public virtual void Execute();<br />    }<br />    abstract class MarsRoverCommand : Command<br />    {<br />        protected MarsRover Rover { get; private set; }<br /> <br />        public MarsRoverCommand(MarsRover rover)<br />        {<br />            this.Rover = rover;<br />        }<br />    }<br />    class BreakCommand : MarsRoverCommand<br />    {<br />        public BreakCommand(MarsRover rover)<br />            : base(rover)<br />        {<br />        } <br />        public override void Execute()<br />        {<br />            Rover.Rotate(-5.0);<br />        }<br />    }<br /> class TurnLeftCommand : MarsRoverCommand<br />    {<br />        public TurnLeftCommand(MarsRover rover)<br />            : base(rover)<br />        {<br />        }<br />        public override void Execute()<br />        {<br />            Rover.Rotate(-5.0);<br />        }<br />    }<br />
    12. 12. Pleasure<br />Pain<br />let swap (x, y) = (y, x)<br />let rotations (x, y, z) = <br /> [ (x, y, z);<br /> (z, x, y);<br /> (y, z, x) ]<br />let reduce f (x, y, z) = <br /> f x + f y + f z<br />Tuple&lt;U,T&gt; Swap&lt;T,U&gt;(Tuple&lt;T,U&gt; t)<br />{<br /> return new Tuple&lt;U,T&gt;(t.Item2, t.Item1)<br />}<br />ReadOnlyCollection&lt;Tuple&lt;T,T,T&gt;&gt; Rotations&lt;T&gt;(Tuple&lt;T,T,T&gt; t) <br />{ <br /> new ReadOnlyCollection&lt;int&gt;<br /> (new Tuple&lt;T,T,T&gt;[]<br /> { new Tuple&lt;T,T,T&gt;(t.Item1,t.Item2,t.Item3); <br /> new Tuple&lt;T,T,T&gt;(t.Item3,t.Item1,t.Item2); <br /> new Tuple&lt;T,T,T&gt;(t.Item2,t.Item3,t.Item1); });<br />}<br />int Reduce&lt;T&gt;(Func&lt;T,int&gt; f,Tuple&lt;T,T,T&gt; t) <br />{ <br /> return f(t.Item1) + f(t.Item2) + f (t.Item3); <br />}<br />
    13. 13. Pleasure<br />Pain<br />type Expr =   <br />    | True   <br />    | And of Expr * Expr   <br />    | Nand of Expr * Expr   <br />    | Or of Expr * Expr   <br />    | Xor of Expr * Expr   <br />    | Not of Expr  <br />public abstract class Expr { }   <br />public abstract class UnaryOp :Expr   <br />{   <br />    public Expr First { get; private set; }   <br />    public UnaryOp(Expr first)   <br />    {   <br />        this.First = first;   <br />    }   <br />}   <br />  <br />public abstract class BinExpr : Expr   <br />{   <br />    public Expr First { get; private set; }   <br />    public Expr Second { get; private set; }   <br />  <br />    public BinExpr(Expr first, Expr second)   <br />    {   <br />        this.First = first;   <br />        this.Second = second;   <br />    }   <br />}   <br />  <br />public class TrueExpr : Expr { }   <br />  <br />public class And : BinExpr   <br />{   <br />    public And(Expr first, Expr second) : base(first, second) { }   <br />}<br />public class Nand : BinExpr   <br />{   <br />    public Nand(Expr first, Expr second) : base(first, second) { }   <br />}   <br />  <br />public class Or : BinExpr   <br />{   <br />    public Or(Expr first, Expr second) : base(first, second) { }   <br />}   <br />  <br />public class Xor : BinExpr   <br />{   <br />    public Xor(Expr first, Expr second) : base(first, second) { }   <br />}   <br />  <br />public class Not : UnaryOp   <br />{   <br />    public Not(Expr first) : base(first) { }   <br />}  <br />   <br /> <br />
    14. 14. Economics<br />
    15. 15. Fun, Fun and More Fun!<br />
    16. 16. You<br />Can<br />Interoperate<br />With<br />Everything<br />
    17. 17. Everything<br />Can<br />Interoperate<br />With<br />You<br />
    18. 18. F#: Influences<br />F#<br />Similar core <br />language<br />Similar object<br />model<br />
    19. 19. F#: Combining Paradigms<br />I&apos;ve been coding in F# lately, for a production task. F# allows you to move smoothly in your programming style... I start with pure functional code, shift slightly towards an object-oriented style, and in production code, I sometimes have to do some imperative programming. <br />I can start with a pure idea, and still finish my project with realistic code. You&apos;re never disappointed in any phase of the project!<br />Julien Laugel, Chief Software Architect, www.eurostocks.com<br />
    20. 20. Let’s WebCrawl...<br />
    21. 21. Orthogonal & Unified Constructs<br />Let “let” simplify your life…<br />Type inference. The safety of C# with the succinctness of a scripting language<br />Bind a static value<br />let data = (1, 2, 3)<br />letf (a, b, c) = <br />let sum = a + b + c <br />letg x = sum + x*x <br />(g a, g b, g c)<br />Bind a static function<br />Bind a local value<br />Bind a local function<br />
    22. 22. Quick Tour<br />Comments <br />// comment<br />(* comment *)<br />/// XML doc comment<br />let x = 1<br />
    23. 23. Quick Tour<br />Overloaded Arithmetic<br />x + yAddition<br />x - ySubtraction<br />x * yMultiplication<br />x / yDivision<br />x % yRemainder/modulus<br />-xUnary negation<br />Booleans<br />not exprBoolean negation<br />expr && exprBoolean “and”<br />expr || exprBoolean “or”<br />
    24. 24. Fundamentals - Whitespace Matters<br />letcomputeDeriative f x = <br />let p1 = f (x - 0.05)<br />let p2 = f (x + 0.05)<br /> (p2 – p1) / 0.1<br />Offside (bad indentation)<br />
    25. 25. Fundamentals - Whitespace Matters<br />letcomputeDeriative f x = <br />let p1 = f (x - 0.05)<br />let p2 = f (x + 0.05)<br /> (p2 – p1) / 0.1<br />
    26. 26. Orthogonal & Unified Constructs<br />Functions: like delegates + unified and simple<br />One simple <br />mechanism, <br />many <br />uses<br />Lambda<br />(fun x -&gt; x + 1)<br />let f x = x + 1<br />(f, f)<br />val f : int -&gt; int<br />predicate = &apos;T -&gt; bool<br />send = &apos;T -&gt; unit<br />Declare a<br />function <br />threadStart = unit -&gt; unit<br />A pair <br />of function values<br />comparer = &apos;T -&gt; &apos;T -&gt; int<br />hasher = &apos;T -&gt; int<br />A function type<br />equality = &apos;T -&gt; &apos;T -&gt; bool<br />
    27. 27. Functional– Pipelines<br />x |&gt; f<br />The pipeline operator<br />
    28. 28. Functional– Pipelines<br />x |&gt; f1<br /> |&gt; f2<br /> |&gt; f3<br />Successive stages <br />in a pipeline<br />
    29. 29. Functional – Pipelining<br />open System.IO<br />let files =<br />Directory.GetFiles(@&quot;c:&quot;, &quot;*.*&quot;,<br />SearchOption.AllDirectories)<br />let totalSize =<br /> files<br /> |&gt; Array.map (fun file -&gt; FileInfo file)<br /> |&gt; Array.map (fun info -&gt; info.Length)<br /> |&gt; Array.sum<br />Sum of file sizes<br />
    30. 30. Immutability the norm…<br />Data is immutable by default<br />Values may not be changed<br />Copy & Update<br />Not Mutate<br />
    31. 31. In Praise of Immutability<br />Immutable objects can be relied upon<br />Immutable objects can transfer between threads<br />Immutable objects can be aliased safely<br />Immutable objects lead to (different) optimization opportunities<br />
    32. 32. Functional Data – Generating Structured Data<br />Union type <br />(no data = enum)<br />type Suit =<br /> | Heart<br /> | Diamond<br /> | Spade<br /> | Club<br /> <br />typePlayingCard =<br /> | Ace of Suit<br /> | King of Suit<br /> | Queen of Suit<br /> | Jack of Suit<br /> | ValueCardofint * Suit<br /> <br />Union type <br />with data<br />
    33. 33. Functional Data – Generating Structured Data (2)<br />let suits = [ Heart; Diamond; Spade; Club ]<br /> <br />letdeckOfCards =<br /> [ for suit in suits do<br />yield Ace suit<br />yield King suit<br />yield Queen suit<br />yield Jack suit<br />for value in 2 .. 10 do<br />yieldValueCard (value, suit) ]<br /> <br />Generate a deck<br />of cards<br />
    34. 34. Weakly Typed? Slow?<br />//F#<br />#light<br />open System<br />let a = 2<br />Console.WriteLine(a)<br />//C#<br />using System;<br />namespace ConsoleApplication1<br />{<br /> class Program<br /> {<br /> static int a()<br /> {<br /> return 2;<br /> }<br /> static void Main(string[] args)<br /> {<br />Console.WriteLine(a); <br /> }<br /> }<br />}<br />Looks Weakly typed?<br />Maybe Dynamic?<br />
    35. 35. F#<br />Yet rich, dynamic<br />Yet succinct<br />
    36. 36. What is Functional Programming?<br />“Working with immutable data”<br />“A language with queries”<br />“A language with lambdas” <br />“A language with pattern matching”<br />“A language with a lighter syntax”<br />“Taming side effects”<br />“Anything but imperative programming”???<br />
    37. 37. Some Micro Trends<br />Communication With Immutable Data<br />Programming With Queries<br />Programming With Lambdas<br />Programming With Pattern Matching<br />Languages with a Lighter Syntax<br />Taming Side Effects<br />REST, HTML, XML, JSON, Haskell, F#, Scala, Clojure, Erlang,...<br />C#, VB, F#, SQL, Kx....<br />C#, F#, Javascript, Scala, Clojure<br />F#, Scala, ...<br />Python, Ruby, F#, ...<br />Erlang, Scala, F#, Haskell, ...<br />
    38. 38. The Huge Trends<br />THE WEB<br />MULTICORE<br />
    39. 39. F# Objects<br />
    40. 40. F# - Objects + Functional<br />type Vector2D (dx:double, dy:double) =<br /> memberv.DX = dx<br /> memberv.DY = dy<br /> memberv.Length = sqrt (dx*dx+dy*dy)<br /> memberv.Scale (k) = Vector2D (dx*k,dy*k)<br />Inputs to object construction<br />Exported properties<br />Exported method<br />
    41. 41. F# - Objects + Functional<br />type Vector2D(dx:double,dy:double) =<br /> let norm2 = dx*dx+dy*dy<br /> memberv.DX = dx<br /> memberv.DY = dy<br /> memberv.Length = sqrt(norm2)<br /> member v.Norm2 = norm2<br />Internal (pre-computed) values and functions<br />
    42. 42. F# - Objects + Functional<br />typeHuffmanEncoding(freq:seq&lt;char*int&gt;) =<br /> ...<br /> &lt; 50 lines of beautiful functional code&gt;<br /> ...<br />memberx.Encode(input: seq&lt;char&gt;) = <br /> encode(input)<br />memberx.Decode(input: seq&lt;char&gt;) = <br /> decode(input)<br />Immutable inputs<br />Internal tables<br />Publish access<br />
    43. 43. F# - Objects + Functional<br />type Vector2D(dx:double,dy:double) =<br /> letmutablecurrDX = dx<br /> letmutablecurrDX = dy<br /> memberv.DX = currDX<br /> memberv.DY = currDY<br /> memberv.Move(x,y) = <br />currDX &lt;- currDX+x<br />currDY &lt;- currDY+y<br />Internal state<br />Publish internal state<br />Mutate internal state<br />
    44. 44. OO <br />and<br />Functional<br />Can<br />Mix<br />
    45. 45. Interlude: Case Study<br />
    46. 46. The adCenter Problem<br />
    47. 47. The Scale of Things<br />Weeks of data in training: <br />N,000,000,000 impressions, 6TB data<br />2 weeks of CPU time during training: <br />2 wks × 7 days × 86,400 sec/day = <br />1,209,600 seconds<br />Learning algorithm speed requirement:<br />N,000 impression updates / sec<br />N00.0 μs per impression update<br />
    48. 48. F# and adCenter<br />4 week project, 4 machine learning experts<br />100million probabilistic variables <br />Processes 6TB of training data <br />Real time processing<br />
    49. 49. AdPredict: What We Observed<br />Quick Coding<br />Agile Coding<br />Scripting<br />Performance<br />Memory-Faithful<br />Succinct<br />Symbolic<br />.NET Integration<br />F#’s powerful type inference means less typing, more thinking<br />Type-inferred code is easily refactored<br />“Hands-on” exploration. <br />Immediate scaling to massive data sets<br />mega-data structures, 16GB machines<br />Live in the domain, not the language<br />Schema compilation and “Schedules”<br />Especially Excel, SQL Server<br />
    50. 50. Smooth Transitions<br />Researcher’s Brain  Realistic, Efficient Code<br />Realistic, Efficient Code  Component<br />Component  Deployment<br />Late 2009 Update... now part of Bing’s “sauce” for advertisers <br />
    51. 51. F# Async/Parallel<br />
    52. 52. F# is a Parallel Language<br />(Multiple active computations)<br />F# is a Reactive Language<br />(Multiple pending reactions)<br />e.g.<br /> GUI Event<br /> Page Load<br />Timer Callback<br />Query Response<br />HTTP Response<br />Web Service Response<br />Disk I/O Completion<br />Agent Gets Message<br />
    53. 53. async { ... }<br />A Building Block for <br />Writing Reactive Code<br />async { ... }<br />For users:<br /> You can run it, but it may take a while<br />Or, your builder says...<br />OK, I can do the job, but I might have to talk to someone else about it. I’ll get back to you when I’m done<br />
    54. 54. async { ... }<br />Asynchronous &quot;non-blocking&quot; action<br />async { let! image = ReadAsync &quot;cat.jpg&quot;<br /> let image2 = f image<br /> do! WriteAsync image2 &quot;dog.jpg&quot;<br /> do printfn &quot;done!&quot; <br /> return image2 }<br />Continuation/<br />Event callback<br />You&apos;re actually writing this (approximately):<br />async.Delay(fun () -&gt; <br />async.Bind(ReadAsync &quot;cat.jpg&quot;, (fun image -&gt;<br /> let image2 = f image<br />async.Bind(writeAsync &quot;dog.jpg&quot;,(fun () -&gt;<br />printfn &quot;done!&quot;<br />async.Return())))))<br />
    55. 55. Code: Web Translation<br />
    56. 56. Typical F# Reactive Architecture<br />Async.Start (async { ... }<br />...<br />Async.Parallel [ ... ]<br />Single Threaded GUI<br />Or<br />Single Threaded Page Handler<br />Or<br />Command Line Driver<br />(queued)<br />new Agent&lt;_&gt;(async { ... })<br />new WebCrawler&lt;_&gt;()<br /> Internally: new Agent&lt;_&gt;(...) ...<br /> event x.Started<br /> event x.CrawledPage<br /> event x.Finished<br />
    57. 57. Taming Asynchronous I/O<br />using System;<br />using System.IO;<br />using System.Threading;<br /> <br />public class BulkImageProcAsync<br />{<br />    public const String ImageBaseName = &quot;tmpImage-&quot;;<br />    public const intnumImages = 200;<br />    public const intnumPixels = 512 * 512;<br /> <br />    // ProcessImage has a simple O(N) loop, and you can vary the number<br />    // of times you repeat that loop to make the application more CPU-<br />    // bound or more IO-bound.<br />    public static intprocessImageRepeats = 20;<br /> <br />    // Threads must decrement NumImagesToFinish, and protect<br />    // their access to it through a mutex.<br />    public static intNumImagesToFinish = numImages;<br />    public static Object[] NumImagesMutex = new Object[0];<br />    // WaitObject is signalled when all image processing is done.<br />    public static Object[] WaitObject = new Object[0];<br />    public class ImageStateObject<br />    {<br />        public byte[] pixels;<br />        public intimageNum;<br />        public FileStreamfs;<br />    }<br /> <br /> <br />    public static void ReadInImageCallback(IAsyncResultasyncResult)<br />    {<br />        ImageStateObject state = (ImageStateObject)asyncResult.AsyncState;<br />        Stream stream = state.fs;<br />        intbytesRead = stream.EndRead(asyncResult);<br />        if (bytesRead != numPixels)<br />            throw new Exception(String.Format<br />                (&quot;In ReadInImageCallback, got the wrong number of &quot; +<br />                &quot;bytes from the image: {0}.&quot;, bytesRead));<br />        ProcessImage(state.pixels, state.imageNum);<br />        stream.Close();<br /> <br />        // Now write out the image.  <br />        // Using asynchronous I/O here appears not to be best practice.<br />        // It ends up swamping the threadpool, because the threadpool<br />        // threads are blocked on I/O requests that were just queued to<br />        // the threadpool. <br />        FileStreamfs = new FileStream(ImageBaseName + state.imageNum +<br />            &quot;.done&quot;, FileMode.Create, FileAccess.Write, FileShare.None,<br />            4096, false);<br />        fs.Write(state.pixels, 0, numPixels);<br />        fs.Close();<br /> <br />        // This application model uses too much memory.<br />        // Releasing memory as soon as possible is a good idea, <br />        // especially global state.<br />        state.pixels = null;<br />        fs = null;<br />        // Record that an image is finished now.<br />        lock (NumImagesMutex)<br />        {<br />            NumImagesToFinish--;<br />            if (NumImagesToFinish == 0)<br />            {<br />                Monitor.Enter(WaitObject);<br />                Monitor.Pulse(WaitObject);<br />                Monitor.Exit(WaitObject);<br />            }<br />        }<br />    }<br /> <br />       public static void ProcessImagesInBulk()<br />    {<br />        Console.WriteLine(&quot;Processing images...  &quot;);<br />        long t0 = Environment.TickCount;<br />        NumImagesToFinish = numImages;<br />        AsyncCallbackreadImageCallback = new<br />            AsyncCallback(ReadInImageCallback);<br />        for (inti = 0; i &lt; numImages; i++)<br />        {<br />            ImageStateObject state = new ImageStateObject();<br />            state.pixels = new byte[numPixels];<br />            state.imageNum = i;<br />            // Very large items are read only once, so you can make the <br />            // buffer on the FileStream very small to save memory.<br />            FileStreamfs = new FileStream(ImageBaseName + i + &quot;.tmp&quot;,<br />                FileMode.Open, FileAccess.Read, FileShare.Read, 1, true);<br />            state.fs = fs;<br />            fs.BeginRead(state.pixels, 0, numPixels, readImageCallback,<br />                state);<br />        }<br /> <br />        // Determine whether all images are done being processed.  <br />        // If not, block until all are finished.<br />        boolmustBlock = false;<br />        lock (NumImagesMutex)<br />        {<br />            if (NumImagesToFinish &gt; 0)<br />                mustBlock = true;<br />        }<br />        if (mustBlock)<br />        {<br />            Console.WriteLine(&quot;All worker threads are queued. &quot; +<br />                &quot; Blocking until they complete. numLeft: {0}&quot;,<br />                NumImagesToFinish);<br />            Monitor.Enter(WaitObject);<br />            Monitor.Wait(WaitObject);<br />            Monitor.Exit(WaitObject);<br />        }<br />        long t1 = Environment.TickCount;<br />        Console.WriteLine(&quot;Total time processing images: {0}ms&quot;,<br />            (t1 - t0));<br />    }<br />}<br />let ProcessImageAsync () =<br />async{letinStream =File.OpenRead(sprintf&quot;Image%d.tmp&quot;i)<br />let!pixels =inStream.ReadAsync(numPixels)<br />letpixels&apos; =TransformImage(pixels,i)<br />letoutStream=File.OpenWrite(sprintf&quot;Image%d.done&quot;i)<br />do!outStream.WriteAsync(pixels&apos;)<br />doConsole.WriteLine&quot;done!&quot; }<br /> <br />letProcessImagesAsyncWorkflow() =<br />Async.Run (Async.Parallel<br />[foriin1 .. numImages-&gt;ProcessImageAsynci ])<br /> <br />Processing 200 images in parallel<br />
    58. 58. Units of Measure<br />
    59. 59. let EarthMass = 5.9736e24&lt;kg&gt;<br />// Average between pole and equator radii<br />let EarthRadius = 6371.0e3&lt;m&gt;<br />// Gravitational acceleration on surface of Earth <br />let g = PhysicalConstants.G * EarthMass / (EarthRadius * EarthRadius)<br />
    60. 60. Microsoft + Eclipse Interoperability<br />For Vijay Rajagopalan<br />Microsoft Interoperability Team<br />
    61. 61. Announcing: Projects fostering interoperability between Eclipse and Microsoft’s platform<br />
    62. 62. 8 Ways to Learn Functional Programming<br /><ul><li>http://cs.hubfs.net
    63. 63. Scala
    64. 64. C# 3.0
    65. 65. ML</li></ul>F# + FSI.exe<br />F# + Reflector<br />Haskell<br />Clojure<br />
    66. 66. Books about F#<br />Visit www.fsharp.net<br />
    67. 67. Books about F#<br />Visit www.fsharp.net<br />
    68. 68. Questions<br />
    69. 69. The many uses of async { ... }<br />Sequencing CPU computations<br />Sequencing I/O requests<br />async { let result1 = fib 39 <br />let result2 = fib 40 <br />return result1 + result2 }<br />async { let!lang = CallDetectLanguageService text<br />let! text2 = CallTranslateTextService (lang, &quot;da&quot;, text)<br />return text2 }<br />
    70. 70. The many uses of async { ... }<br />Parallel CPU computations<br />Parallel I/O requests<br />Async.Parallel [ async { return fib 39 };<br />async { return fib 40 }; ]<br />Async.Parallel<br /> [ for targetLang in languages -&gt; translate (text, language) ]<br />
    71. 71. The many uses of async { ... }<br />Sequencing CPU computations and I/O requests<br />async { let!lang = callDetectLanguageService text<br />let! text2 = callTranslateTextService (lang, &quot;da&quot;, text)<br />let text3 = postProcess text <br />return text3 }<br />
    72. 72. The many uses of async { ... }<br />Repeating tasks<br />Repeating tasks with state<br />async { while true do<br />let!msg = queue.ReadMessage()<br /> &lt;process message&gt; }<br />let rec loop () = <br />async { let!msg = queue.ReadMessage()<br />printfn &quot;got a message&quot;<br />return! loop () }<br />loop ()<br />let rec loop count = <br />async { let!msg = queue.ReadMessage()<br />printfn &quot;got a message&quot;<br />return! loop (count + msg) }<br />loop 0<br />
    73. 73. The many uses of async { ... }<br />Representing Agents (approximate) <br /> let queue = new Queue()<br /> let rec loop count = <br />async { let!msg = queue.ReadMessage()<br />printfn &quot;got a message&quot;<br />return! loop (count + msg) }<br />Async.Start (loop 0)<br />queue.Enqueue 3<br />queue.Enqueue 4<br />
    74. 74. The many uses of async { ... }<br />Representing Agents (real) <br />let agent = <br />Agent.Start(<br />let rec loop count = <br />async { let!msg = queue.ReadMessage()<br />printfn &quot;got a message&quot;<br />return! loop (count + msg) }<br /> loop 0)<br />agent.Post 3<br />agent.Post 4<br />Note:<br />type Agent&lt;&apos;T&gt; = MailboxProcessor&lt;&apos;T&gt;<br />
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×