fp day 2011 - turning to the functional side (using c# & f#)

52
Turning to the Functional side (Using C# and F#) Phil Trelford http:// trelford.com/blog @ptrelford Tomas Petricek http://tomasp.net /blog @tomaspetricek

Upload: phillip-trelford

Post on 06-May-2015

3.025 views

Category:

Technology


0 download

DESCRIPTION

Slides presented at FP Day 2011 in Cambridge

TRANSCRIPT

Page 1: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Turning to the Functional side(Using C# and F#)

Phil Trelfordhttp://trelford.com/blog

@ptrelford

Tomas Petricekhttp://tomasp.net/blog

@tomaspetricek

Page 2: FP Day 2011 - Turning to the Functional Side (using C# & F#)

About Us

» Tomas • Author of F# book for C# programmers• Worked with the F# team at Microsoft• First blogged about F# in May 2006

» Phil• Software Developer and Architect• Worked on first F# applications at Microsoft• Co-organizer of London F# User Group

» http://functional-programming.net

Page 3: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Tutorial

Goals

» Introduce Functional Concepts with F# and C#

Non-goals

» Provide in-depth understanding

» Mass conversion to functional programming cult

» Sell books

Page 4: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Thoughtworks Technology Radar July 2011

Page 5: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Visual F#

Page 6: FP Day 2011 - Turning to the Functional Side (using C# & F#)

The F in F# stands for FUN

Page 7: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Halo 3 with F# Skills

Page 8: FP Day 2011 - Turning to the Functional Side (using C# & F#)

XBLA: Path to Go – F# AI

Page 9: FP Day 2011 - Turning to the Functional Side (using C# & F#)

F#

» Strongly Typed

» Functional

» Object Orientated

» Open Source

» .Net language

» In Visual Studio

Page 10: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Functional Programing

» Pure Functions

» Higher Order Functions

» Pattern Matching

Page 11: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Pure Functions - Excel

Page 12: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Higher Order Functions

let map f xs = seq {

for x in xs do

yield f x

}

let reduce f init items =

let mutable current = init

for item in items do

current <- f current item

current

F# Map/Reduce C# Map/Reduce

public static

IEnumerable<R> Map<T, R>

(this IEnumerable<T> xs,

Func<T, R> f)

{

foreach (var x in xs)

yield return f(x);

}

public static R

Reduce<T, R>

(this IEnumerable<T> xs,

R init,

Func<R, T, R> f)

{

var current = init;

foreach (var x in xs)

current = f(current, x);

return current;

}

Page 13: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Pattern Matching

match day with

| 0 -> "Sunday"

| 1 -> "Monday"

| 2 -> "Tuesday"

| 3 -> "Wednesday"

| 4 -> "Thursday"

| 5 -> "Friday"

| 6 -> "Saturday"

| _ –>

invalidArg "Invalid day"

F# C#

switch (day) {

case 0: return "Sunday";

case 1: return "Monday";

case 2: return "Tuesday";

case 3: return "Wednesday";

case 4: return "Thursday";

case 5: return "Friday";

case 6: return "Saturday";

default:

throw new

ArgumentException("day");

}

Page 14: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Light Syntax

type Person(name:string,age:int) =

/// Full name

member person.Name = name

/// Age in years

member person.Age = age

F# C#public class Person

{

public Person(string name, int age)

{

_name = name;

_age = age;

}

private readonly string _name;

private readonly int _age;

/// <summary>

/// Full name

/// </summary>

public string Name

{

get { return _name; }

}

/// <summary>

/// Age in years

/// </summary>

public int Age

{

get { return _age; }

}

}

Page 15: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Functional data structures

» A way of thinking about problems

» Model data using composition of primitives

Combine two values of different typesTuple

Represents one of several optionsDiscriminated

Union

Zero or more values of the same typeList

Page 16: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Tuples: Containers for a few different things

Page 17: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Discriminated Unions: Exclusive alternatives

Page 18: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Representing event schedule

Object-oriented way

» Easy to add new cases» Hard to add new functions

Functional way

» Easy to add new functions» Hard to add new cases

GetNextOccurrence() : DateTime

Schedule

Never RepeatedlyOnce

Tag : ScheduleType

Schedule

Never RepeatedlyOnce

» Good thing about F# and Scala – you can use both!

Page 19: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Cutting the caterpillar

Head

Head

Head

Head

Head

End!

Page 20: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Functional Lists in C#

» List is either empty or nonempty

• In C#, a class hierarchy with two classes• In F#, a discriminated union with two cases

List

EmptyNonempty(head, tail)

Page 21: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Functional lists in C#

public class FunctionalList<T> { // Creates a new list that is empty public FunctionalList(); // Creates a non-empty list public FunctionalList(T head, FunctionalList<T> tail);

// Is the list empty? public bool IsEmpty { get; }

// Properties valid for a non-empty list public T Head { get; } public FunctionalList<T> Tail { get; }}

Page 22: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Domain Modelling

» Retail Domain -> Testing

» http://tomasp.net/fpday.zip

Page 23: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Processing Stock Prices

Page 24: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Yahoo Stock Prices

» Data stored in a CSV file

» Read and print all data

Date,Open,High,Low,Close,Volume,Adj Close2011-10-12,407.34,409.25,400.14,402.19,22206600,402.192011-10-11,392.57,403.18,391.50,400.29,21609800,400.292011-10-10,379.09,388.81,378.21,388.81,15769200,388.81

open System.IO

let dir = __SOURCE_DIRECTORY__ + "\\data\\aapl.csv"let lines = File.ReadAllLines(dir)for line in lines do printfn "%s" line

Page 25: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Parsing CSV data

» Get some data for testing

» Using arrays in F#

» Converting strings to numbers

let line1 = lines |> Seq.headlet line2 = lines |> Seq.skip 1 |> Seq.head

let arr = str.Split([| ',' |])arr.[0]

float "12.34"DateTime.Parse("1985-05-02")

Page 26: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Iterate over lines, parse CSV and print date & price

TASK #1

Page 27: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Sequence expressions

» Exploring data using imperative loops

» Can be turned into a sequence expression…

• Result has a type seq<int * float> (IEnumerable)• Brackets: [| … |] for arrays, [ … ] for lists, set [ … ] for sets

for year, value in yearlyAverages do if value < 25.0 then printfn "%d (only %f)" year value

let badYears = seq { for year, value in yearlyAverages do if value < 25.0 then yield year, value }

Page 28: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Turn the parsing into a sequence expression

TASK #2

Page 29: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Organizing Source Code

» Compiled Libraries• Allow C# users call F# code• Encapsulate (complete) functionality

» F# Script Files• Great for explorative programming• Script can load some other files

// File1.fsxmodule StockData

let getData name = name, 99.0

// File2.fsx#load "File1.fsx"open StockData

getData "MSFT"

Page 30: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Write function that parses specified CSV file

TASK #3

Page 31: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Processing Data in F#

» Writing data processing query in F#

» Seq module provides functions for IEnumerable• But some operations make only sense for arrays/lists

» Sequence expressions provide query-like syntax

StockData.MSFT |> Seq.filter (fun stock -> stock.Close - stock.Open > 7.0)|> Seq.map (fun stock -> stock.Date)|> Seq.iter (printfn "%A")

Lambda function

Partial function applicationCustom

operators

All types are inferred

Page 32: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Useful functions

» Basic Functions• Seq.filter – filter elements using predicate (aka Where) • Seq.map – turn values into different (aka Select)

» Aggregating all elements of a sequence• Seq.max, Seq.min, Seq.averag – the obvious• Seq.fold – general aggregation

» Grouping elements of a sequence• Seq.groupBy – group using key• Seq.pairwise – adjacent pairs• Seq.windowed – sliding window

» For more see: http://fssnip.net/categories/Sequences

Page 33: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Calculate standard deviation of the data

TASK #5

√∑ (𝑣 𝑖−𝑎𝑣𝑔)2

𝑐𝑜𝑢𝑛𝑡

Find number of days when closing price is larger than opening price by more than $5.

TASK #4

Page 34: FP Day 2011 - Turning to the Functional Side (using C# & F#)

FSharpChart library

» Easy to use charting library for F#• Based on .NET 4.0 Chart Controls (WinForms/ASP.NET)

» Designed to fit nicely with F#

[ for st in StockData.MSFT -> st.Date, st.Open ]|> FSharpChart.Line

Light-weight syntax for projections

Line chart expects value or key *

value

[ for st in StockData.MSFT -> st.Date, st.Open ]|> FSharpChart.Line|> FSharpChart.WithTitle ( Text = "Microsoft Stock Prices", Font = new System.Drawing.Font("Calibri", 16.0f) )

Page 35: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Create chart that shows values with 5 day average.This can be done using Seq.windowed

TASK #6

Create chart that shows prices together with standard deviation (over 5 day window) range

TASK #7

Page 36: FP Day 2011 - Turning to the Functional Side (using C# & F#)

» Observable• Source generates data

(push-based model)• Process data on-the-fly• F# libs and .NET Rx

» Parallel Sequence• Parallel implementation• Process large amount

of in-memory data• Available in F# PowerPack

prices |> Seq.windowed 100 |> PSeq.ordered |> PSeq.map averageAndSdv

pricesEvent |> Observable.windowed 100 |> Observable.map averageAndSdv

In-memory, but processed in

parallel

Processing live data on

the fly

Processing data live and in parallel

Page 37: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Async Programming

Page 38: FP Day 2011 - Turning to the Functional Side (using C# & F#)

The Problem

» Problems with I/O bound computations• Avoid blocking user interface• Handle many requests concurrently

» What needs to be done differently?• Avoid creating and blocking too many threads• Reliability and scalability are essential• React to events (from I/O or even GUI)

Page 39: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Using Explicit Callbacks

» Event-based programming model

• Callback called when operation completes• Gaining popularity (e.g. Node.js)

» Does not solve all problems• Control structures don’t work (loops, try-catch, …)• Difficult to work with state

HttpServer.Start("http://localhost:8080/", fun ctx -> WebClient.DownloadAsync(getProxyUrl(ctx), fun data -> ctx.ResponseStream.WriteAsync(data, fun res -> ctx.ResponseStream.Close())))

Page 40: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Synchronous to Asynchronous

» What would we want to write?

» Turning synchronous to asynchronous• Wrap body in an async block• Asynchronous calls using do! and let! • Supports all F# control flow constructs

let copyPageTo url outputStream = try let html = WebClient.AsyncDownload(url) outputStream.AsyncWrite(html) finally ctx.ResponseStream.Close()

let copyPageTo url outputStream = async { try let! html = WebClient.AsyncDownload(url) do! outputStream.AsyncWrite(html) finally ctx.ResponseStream.Close() }

Page 41: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Async User Interfaces

Page 42: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Async GUI programming

» Controlling semaphore light• Using int or enum to keep current state?• Difficult to read – what does state represent?

» Better approach – asynchronous waiting• Loop switches between state• Asynchronous waiting for events

green orange red

Page 43: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Writing loops using workflows

» Using standard language constructs

» Key idea – asynchronous waiting• F# events are first class values• Can use functional & imperative style

let semaphoreStates() = async { while true do for current in [ green; orange; red ] do let! md = Async.AwaitEvent(this.MouseDown) display(current) }

Infinite loop!

Wait for click

Page 44: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Checkout application workflow

» Think of a simple while loop

Print summary

Scan items

Complete purchaseNext customer

Startup

Page 45: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Asynchronous and concurrent programming

» Asynchronous GUI in Checkout example• Single-threaded thanks to Async.StartImmediate• Easy way to encode control flow

» Parallel programming• Workflows are non-blocking computations• Run workflows in parallel with Async.Parallel

» Concurrent programming• Compose application from (thousands of) agents• Agents communicate using messages

Page 46: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Summary

» FP is already in the mainstream

» FP languages are ready

» Start small, go big• Language Orientated Programming• Exploratory and Scripting• Asynchronous & Concurrency• Technical Computing• Testing

Page 47: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Summary

Don’t underestimate the power of the

functional side

Page 48: FP Day 2011 - Turning to the Functional Side (using C# & F#)

ICFP 2011

Page 49: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Meet the F#ers

@rickasaurus

@tomaspetricek

@dmohl

Page 50: FP Day 2011 - Turning to the Functional Side (using C# & F#)

F# Books

Page 51: FP Day 2011 - Turning to the Functional Side (using C# & F#)

» http://functional-programming.net

On the horizon

http://meetup.com/fsharplondonEvery 6 weeks @ Skills Matter

Page 52: FP Day 2011 - Turning to the Functional Side (using C# & F#)

Q & A

» http://Fsharp.net

» http://fssnip.net

» http://tomasp.net/blog

» http://trelford.com/blog