Top Banner
Taking Functional Programming into the Mainstream Don Syme, Principal Researcher Microsoft Research, Cambridge
71

Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Dec 17, 2014

Download

Technology

Lynn Gayowski

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.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Taking Functional Programming into the MainstreamDon Syme, Principal ResearcherMicrosoft Research, Cambridge

Page 2: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Disclaimer

• I’m a Microsoft Guy. I’m a .NET Fan. I will be using Visual Studio in this talk.

• This talk is offered in a spirit of cooperation and idea exchange. Please accept it as such

Page 3: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Topics

• Why is Microsoft Investing in Functional Programming?

• Some Simple F# Programming

• A Taste of Parallel/Reactive with F#

• An Announcement

Page 4: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Why is Microsoft investing in Functional Programming?

Page 5: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

What Investments?

• C# (Generics, LINQ)• F#• Reactive Framework• Haskell• VB, Python, Ruby

Page 6: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Simplicity

Page 7: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Economics

Page 8: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Fun, Fun and More Fun!

Page 9: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Simplicity

Page 10: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Code!

//F#open Systemlet a = 2Console.WriteLine a

//C#using System;

namespace ConsoleApplication1{ class Program { static int a() { return 2; } static void Main(string[] args) { Console.WriteLine(a);

} }}

More Noise Than Signal!

Page 11: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Pleasure type Command = Command of (Rover -> unit)

let BreakCommand     = Command(fun rover -> rover.Accelerate(-1.0))

let TurnLeftCommand  = Command(fun rover -> rover.Rotate(-5.0<degs>)) 

Pain   abstract class Command    {        public virtual void Execute();    }    abstract class MarsRoverCommand : Command    {        protected MarsRover Rover { get; private set; }         public MarsRoverCommand(MarsRover rover)        {            this.Rover = rover;        }    }    class BreakCommand : MarsRoverCommand    {        public BreakCommand(MarsRover rover)            : base(rover)        {        }         public override void Execute()        {            Rover.Rotate(-5.0);        }    } class TurnLeftCommand : MarsRoverCommand    {        public TurnLeftCommand(MarsRover rover)            : base(rover)        {        }        public override void Execute()        {            Rover.Rotate(-5.0);        }    }

Page 12: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Pleasure

let swap (x, y) = (y, x)

let rotations (x, y, z) = [ (x, y, z); (z, x, y); (y, z, x) ]

let reduce f (x, y, z) = f x + f y + f z

Pain

Tuple<U,T> Swap<T,U>(Tuple<T,U> t){ return new Tuple<U,T>(t.Item2, t.Item1)}

ReadOnlyCollection<Tuple<T,T,T>> Rotations<T>(Tuple<T,T,T> t)

{ new ReadOnlyCollection<int> (new Tuple<T,T,T>[] { new

Tuple<T,T,T>(t.Item1,t.Item2,t.Item3); new

Tuple<T,T,T>(t.Item3,t.Item1,t.Item2); new

Tuple<T,T,T>(t.Item2,t.Item3,t.Item1); });}

int Reduce<T>(Func<T,int> f,Tuple<T,T,T> t) { return f(t.Item1) + f(t.Item2) + f

(t.Item3); }

Page 13: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Pleasuretype Expr =       | True       | And of Expr * Expr       | Nand of Expr * Expr       | Or of Expr * Expr       | Xor of Expr * Expr       | Not of Expr  

Painpublic abstract class Expr { }   public abstract class UnaryOp :Expr   {       public Expr First { get; private set

; }       public UnaryOp(Expr first)       {           this.First = first;       }   }     public abstract class BinExpr : Expr   {       public Expr First { get; private set

; }       public Expr Second { get; private se

t; }         public BinExpr(Expr first, Expr seco

nd)       {           this.First = first;           this.Second = second;       }   }     public class TrueExpr : Expr { }     public class And : BinExpr   {       public And(Expr first, Expr second) 

: base(first, second) { }   }public class Nand : BinExpr   {       public Nand(Expr first, Expr second)

 : base(first, second) { }   }     public class Or : BinExpr   {       public Or(Expr first, Expr second) :

 base(first, second) { }   }     public class Xor : BinExpr   {       public Xor(Expr first, Expr second) 

: base(first, second) { }   }     public class Not : UnaryOp   {       public Not(Expr first) : base(first)

 { }   }      

Page 14: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Economics

Page 15: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Fun, Fun and More Fun!

Page 16: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

YouCanInteroperateWithEverything

Page 17: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

EverythingCanInteroperateWithYou

Page 18: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

F#: Influences

OCaml

C#/.NET

F#

Similar core language

Similar objectmodel

Page 19: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

F#: Combining Paradigms

I'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.

I can start with a pure idea, and still finish my project with realistic code. You're never disappointed in any phase of the project!

Julien Laugel, Chief Software Architect, www.eurostocks.com

Page 20: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Let’s WebCrawl...

Page 21: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Orthogonal & Unified Constructs

• Let “let” simplify your life…

let data = (1, 2, 3)

let f (a, b, c) = let sum = a + b + c let g x = sum + x*x (g a, g b, g c)

Bind a static value

Bind a static function

Bind a local value

Bind a local function

Type inference. The safety of C# with the

succinctness of a scripting language

Page 22: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Quick Tour

Comments // comment

(* comment *)

/// XML doc commentlet x = 1

Page 23: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Quick Tour

Booleansnot expr Boolean negationexpr && expr Boolean “and”expr || expr Boolean “or”

Overloaded Arithmeticx + y Addition x - y Subtraction x * y Multiplication x / y Division x % y Remainder/modulus -x Unary negation

Page 24: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Fundamentals - Whitespace Matterslet computeDeriative f x = let p1 = f (x - 0.05)

let p2 = f (x + 0.05)

(p2 – p1) / 0.1

Offside (bad indentation)

Page 25: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Fundamentals - Whitespace Matterslet computeDeriative f x = let p1 = f (x - 0.05)

let p2 = f (x + 0.05)

(p2 – p1) / 0.1

Page 26: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Orthogonal & Unified Constructs

• Functions: like delegates + unified and simple

(fun x -> x + 1)

let f x = x + 1

(f, f)

val f : int -> int

Lambda

Declare afunction

A pair of function values

predicate = 'T -> bool

send = 'T -> unit

threadStart = unit -> unit

comparer = 'T -> 'T -> int

hasher = 'T -> int

equality = 'T -> 'T -> bool

One simple mechanism,

many uses

A function type

Page 27: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Functional– Pipelines

x |> f

The pipeline operator

Page 28: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Functional– Pipelines

x |> f1 |> f2 |> f3

Successive stages in a pipeline

Page 29: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Functional – Pipelining

open System.IO

let files = Directory.GetFiles(@"c:\", "*.*", SearchOption.AllDirectories)

let totalSize = files |> Array.map (fun file -> FileInfo file) |> Array.map (fun info -> info.Length) |> Array.sum

Sum of file sizes

Page 30: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Immutability the norm…

Values may not be

changed

Data is immutable by

default

Not Mutate

Copy & Update

Page 31: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

In Praise of Immutability

• Immutable objects can be relied upon

• Immutable objects can transfer between threads

• Immutable objects can be aliased safely

• Immutable objects lead to (different) optimization opportunities

Page 32: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Functional Data – Generating Structured Data

type Suit = | Heart | Diamond | Spade | Club type PlayingCard = | Ace of Suit | King of Suit | Queen of Suit | Jack of Suit | ValueCard of int * Suit 

Union type (no data =

enum)

Union type with data

Page 33: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Functional Data – Generating Structured Data (2)

let suits = [ Heart; Diamond; Spade; Club ] let deckOfCards = [ for suit in suits do yield Ace suit yield King suit yield Queen suit yield Jack suit for value in 2 .. 10 do yield ValueCard (value, suit) ] 

Generate a deck

of cards

Page 34: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

//F##lightopen Systemlet a = 2Console.WriteLine(a)

//C#using System;

namespace ConsoleApplication1{ class Program { static int a() { return 2; }

static void Main(string[] args)

{ Console.WriteLine(a);

} }}

Looks Weakly typed?

Maybe Dynamic?

Weakly Typed? Slow?

Page 35: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Typed Untyped

EfficientInterpretedReflection

Invoke

F#Yet rich, dynamic

Yet succinct

Page 36: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

What is Functional Programming?

• “Working with immutable data”• “A language with queries”• “A language with lambdas” • “A language with pattern matching”• “A language with a lighter syntax”• “Taming side effects”

“Anything but imperative

programming”???

Page 37: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Some Micro Trends

• Communication With Immutable Data

• Programming With Queries• Programming With Lambdas• Programming With Pattern Matching• Languages with a Lighter Syntax• Taming Side Effects

REST, HTML, XML, JSON, Haskell, F#, Scala, Clojure, Erlang,...

C#, VB, F#, SQL,

Kx....

C#, F#, Javascript,

Scala, Clojure

F#, Scala, ...

Python, Ruby, F#, ...

Erlang, Scala, F#, Haskell, ...

Page 38: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

The Huge Trends

THE WEB MULTICORE

Page 39: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

F# Objects

Page 40: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

F# - Objects + Functional

type Vector2D (dx:double, dy:double) =

member v.DX = dx member v.DY = dy member v.Length = sqrt (dx*dx+dy*dy) member v.Scale (k) = Vector2D (dx*k,dy*k)

Inputs to object

construction

Exported properties

Exported method

Page 41: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

F# - Objects + Functional

type Vector2D(dx:double,dy:double) =

let norm2 = dx*dx+dy*dy

member v.DX = dx member v.DY = dy member v.Length = sqrt(norm2) member v.Norm2 = norm2

Internal (pre-computed) values and functions

Page 42: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

F# - Objects + Functional

type HuffmanEncoding(freq:seq<char*int>) = ... < 50 lines of beautiful functional code> ...

member x.Encode(input: seq<char>) = encode(input) member x.Decode(input: seq<char>) = decode(input)

Immutable inputs

Internal tables

Publish access

Page 43: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

F# - Objects + Functional

type Vector2D(dx:double,dy:double) =

let mutable currDX = dx

let mutable currDX = dy

member v.DX = currDX member v.DY = currDY member v.Move(x,y) = currDX <- currDX+x currDY <- currDY+y

Internal state

Publish internal

state

Mutate internal

state

Page 44: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

OO andFunctionalCanMix

Page 45: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Interlude: Case Study

Page 46: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

The adCenter Problem

Page 47: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

The Scale of Things

• Weeks of data in training: N,000,000,000 impressions, 6TB data

• 2 weeks of CPU time during training: 2 wks × 7 days × 86,400 sec/day =

1,209,600 seconds• Learning algorithm speed requirement:

• N,000 impression updates / sec• N00.0 μs per impression update

Page 48: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

F# and adCenter

• 4 week project, 4 machine learning experts

• 100million probabilistic variables

• Processes 6TB of training data

• Real time processing

Page 49: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

AdPredict: What We Observed

• Quick Coding

• Agile Coding

• Scripting

• Performance

• Memory-Faithful

• Succinct

• Symbolic

• .NET Integration

F#’s powerful type inference means less typing, more

thinking

Type-inferred code is easily refactored

“Hands-on” exploration.

Immediate scaling to massive data

setsmega-data

structures, 16GB machines

Live in the domain, not the language

Schema compilation and

“Schedules”Especially Excel, SQL Server

Page 50: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Smooth Transitions

• Researcher’s Brain Realistic, Efficient Code

• Realistic, Efficient Code Component

• Component Deployment

Late 2009 Update... now part of Bing’s “sauce” for advertisers

Page 51: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

F# Async/Parallel

Page 52: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

F# is a Parallel Language

(Multiple active computations)

F# is a Reactive Language

(Multiple pending reactions)

e.g. GUI Event Page Load

Timer CallbackQuery ResponseHTTP Response

Web Service ResponseDisk I/O

CompletionAgent Gets Message

Page 53: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

async { ... }

• For users: You can run it, but it may take a while

Or, your builder says...

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

async { ... }

A Building Block for Writing Reactive Code

Page 54: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

async { ... }

async.Delay(fun () -> async.Bind(ReadAsync "cat.jpg", (fun image -> let image2 = f image async.Bind(writeAsync "dog.jpg",(fun () -> printfn "done!" async.Return())))))

async { let! image = ReadAsync "cat.jpg" let image2 = f image do! WriteAsync image2 "dog.jpg" do printfn "done!" return image2 }

Continuation/Event callback

Asynchronous "non-blocking"

action

You're actually writing this (approximately):

Page 55: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Code: Web Translation

Page 56: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Typical F# Reactive Architecture

Single Threaded GUI

Or

Single Threaded Page Handler

Or

Command Line Driver

Async.Parallel [ ... ]

new Agent<_>(async { ... })

new WebCrawler<_>() Internally: new Agent<_>(...) ...

event x.Started event x.CrawledPage event x.Finished

...

Async.Start (async { ... }

(queued)

Page 57: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Taming Asynchronous I/O

using System;using System.IO;using System.Threading; public class BulkImageProcAsync{    public const String ImageBaseName = "tmpImage-";    public const int numImages = 200;    public const int numPixels = 512 * 512;     // ProcessImage has a simple O(N) loop, and you can vary the number    // of times you repeat that loop to make the application more CPU-    // bound or more IO-bound.    public static int processImageRepeats = 20;     // Threads must decrement NumImagesToFinish, and protect    // their access to it through a mutex.    public static int NumImagesToFinish = numImages;    public static Object[] NumImagesMutex = new Object[0];    // WaitObject is signalled when all image processing is done.    public static Object[] WaitObject = new Object[0];    public class ImageStateObject    {        public byte[] pixels;        public int imageNum;        public FileStream fs;    }  

    public static void ReadInImageCallback(IAsyncResult asyncResult)    {        ImageStateObject state = (ImageStateObject)asyncResult.AsyncState;        Stream stream = state.fs;        int bytesRead = stream.EndRead(asyncResult);        if (bytesRead != numPixels)            throw new Exception(String.Format                ("In ReadInImageCallback, got the wrong number of " +                "bytes from the image: {0}.", bytesRead));        ProcessImage(state.pixels, state.imageNum);        stream.Close();         // Now write out the image.          // Using asynchronous I/O here appears not to be best practice.        // It ends up swamping the threadpool, because the threadpool        // threads are blocked on I/O requests that were just queued to        // the threadpool.         FileStream fs = new FileStream(ImageBaseName + state.imageNum +            ".done", FileMode.Create, FileAccess.Write, FileShare.None,            4096, false);        fs.Write(state.pixels, 0, numPixels);        fs.Close();         // This application model uses too much memory.        // Releasing memory as soon as possible is a good idea,         // especially global state.        state.pixels = null;        fs = null;        // Record that an image is finished now.        lock (NumImagesMutex)        {            NumImagesToFinish--;            if (NumImagesToFinish == 0)            {                Monitor.Enter(WaitObject);                Monitor.Pulse(WaitObject);                Monitor.Exit(WaitObject);            }        }    }

        public static void ProcessImagesInBulk()    {        Console.WriteLine("Processing images...  ");        long t0 = Environment.TickCount;        NumImagesToFinish = numImages;        AsyncCallback readImageCallback = new            AsyncCallback(ReadInImageCallback);        for (int i = 0; i < numImages; i++)        {            ImageStateObject state = new ImageStateObject();            state.pixels = new byte[numPixels];            state.imageNum = i;            // Very large items are read only once, so you can make the             // buffer on the FileStream very small to save memory.            FileStream fs = new FileStream(ImageBaseName + i + ".tmp",                FileMode.Open, FileAccess.Read, FileShare.Read, 1, true);            state.fs = fs;            fs.BeginRead(state.pixels, 0, numPixels, readImageCallback,                state);        }         // Determine whether all images are done being processed.          // If not, block until all are finished.        bool mustBlock = false;        lock (NumImagesMutex)        {            if (NumImagesToFinish > 0)                mustBlock = true;        }        if (mustBlock)        {            Console.WriteLine("All worker threads are queued. " +                " Blocking until they complete. numLeft: {0}",                NumImagesToFinish);            Monitor.Enter(WaitObject);            Monitor.Wait(WaitObject);            Monitor.Exit(WaitObject);        }        long t1 = Environment.TickCount;        Console.WriteLine("Total time processing images: {0}ms",            (t1 - t0));    }}

let ProcessImageAsync () = async { let inStream = File.OpenRead(sprintf "Image%d.tmp" i) let! pixels = inStream.ReadAsync(numPixels) let pixels' = TransformImage(pixels,i) let outStream = File.OpenWrite(sprintf "Image%d.done" i) do! outStream.WriteAsync(pixels') do Console.WriteLine "done!" } let ProcessImagesAsyncWorkflow() = Async.Run (Async.Parallel [ for i in 1 .. numImages -> ProcessImageAsync i ]) 

Processing 200 images in parallel

Page 58: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Units of Measure

Page 59: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

let EarthMass = 5.9736e24<kg>

// Average between pole and equator radiilet EarthRadius = 6371.0e3<m>

// Gravitational acceleration on surface of Earth let g = PhysicalConstants.G * EarthMass / (EarthRadius * EarthRadius)

Page 60: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Microsoft + Eclipse Interoperability

For Vijay RajagopalanMicrosoft Interoperability Team

Page 61: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

•Enh

anc

e

Ecli

pse

dev

elop

er

exp

erie

nce

on

Win

dow

s 7

Eclipse on Windows 7

•Plu

g-in

for

Ecli

pse

to

buil

d

Silv

erli

ght

Rich

Inte

rnet

App

licat

ions

Eclipse Tools for

Silverlight

•Ena

ble

PHP

,

Java

dev

elop

ers

usin

g

Ecli

pse

to

buil

d &

depl

oy

on

Azu

re

Windows Azure +

Eclipse / PHP

Announcing: Projects fostering interoperability between Eclipse and Microsoft’s platform

Page 62: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

8 Ways to Learn Functional Programming

• F# + FSI.exe

• F# + Reflector

• Haskell

• Clojure

• http://cs.hubfs.net

• Scala

• C# 3.0

• ML

Page 63: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Books about F#

Visit www.fsharp.net

Page 64: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Books about F#

Visit www.fsharp.net

Page 65: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

Questions

Page 66: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

The many uses of async { ... }

• Sequencing CPU computations

• Sequencing I/O requests

async { let result1 = fib 39 let result2 = fib 40 return result1 + result2 }

async { let! lang = CallDetectLanguageService text let! text2 = CallTranslateTextService (lang, "da", text) return text2 }

Page 67: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

The many uses of async { ... }

• Parallel CPU computations

• Parallel I/O requests

Async.Parallel [ async { return fib 39 }; async { return fib 40 }; ]

Async.Parallel [ for targetLang in languages -> translate (text, language) ]

Page 68: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

The many uses of async { ... }

• Sequencing CPU computations and I/O requestsasync { let! lang = callDetectLanguageService text

let! text2 = callTranslateTextService (lang, "da", text) let text3 = postProcess text return text3 }

Page 69: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

The many uses of async { ... }

• Repeating tasks

• Repeating tasks with state

async { while true do let! msg = queue.ReadMessage() <process message> }

let rec loop count = async { let! msg = queue.ReadMessage() printfn "got a message" return! loop (count + msg) }

loop 0

let rec loop () = async { let! msg = queue.ReadMessage() printfn "got a message" return! loop () }loop ()

Page 70: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

The many uses of async { ... }

• Representing Agents (approximate) let queue = new Queue()

let rec loop count = async { let! msg = queue.ReadMessage() printfn "got a message" return! loop (count + msg) } Async.Start (loop 0)

queue.Enqueue 3queue.Enqueue 4

Page 71: Taking Functional Programming Into The Mainstream - Eclipse Summit Europe 2009

The many uses of async { ... }

• Representing Agents (real) let agent = Agent.Start( let rec loop count = async { let! msg = queue.ReadMessage() printfn "got a message" return! loop (count + msg) } loop 0)

agent.Post 3agent.Post 4Note:

type Agent<'T> = MailboxProcessor<'T>