F# Overview: Immutable Data + Pure Functions. Acknowledgements Authored by – Thomas Ball, MSR Redmond Includes content from the F# team.

Slides:



Advertisements
Similar presentations
Functional Programming Lecture 10 - type checking.
Advertisements

Formal Models of Computation Part II The Logic Model
Haskell user defined types data Temp = Cold|Hot|Warm deriving (Show,Eq, Ord, Enum) -- to enable printing to screen -- comparing for equality -- comparison.
7-Jun-14 Lists. Arrays and Lists Arrays are a fixed length and occupy sequential locations in memory This makes random access (for example, getting the.
Modern Programming Languages, 2nd ed.
ML Lists.1 Standard ML Lists. ML Lists.2 Lists A list is a finite sequence of elements. [3,5,9] ["a", "list" ] [] Elements may appear more than once [3,4]
ML Lists.1 Standard ML Lists. ML Lists.2 Lists  A list is a finite sequence of elements. [3,5,9] ["a", "list" ] []  Elements may appear more than once.
1 Decision Procedures An algorithmic point of view Equality Logic and Uninterpreted Functions.
A Third Look At ML 1. Outline More pattern matching Function values and anonymous functions Higher-order functions and currying Predefined higher-order.
Introduction to OCaml Slides prepared by Matt Gruskin Some material borrowed from the CIS 500 lecture notes.
Higher-order functions in OCaml. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function.
... a programming language. ...a functional programming language.
CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists Dan Grossman Winter 2013.
F28PL1 Programming Languages Lecture 14: Standard ML 4.
CMSC 330: Organization of Programming Languages Tuples, Types, Conditionals and Recursion or “How many different OCaml topics can we cover in a single.
ML Lists.1 Standard ML Lists. ML Lists.2 Lists  A list is a finite sequence of elements. [3,5,9] ["a", "list" ] []  ML lists are immutable.  Elements.
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
By Neng-Fa Zhou Functional Programming 4 Theoretical foundation –Church’s -calculus expressions and evaluation rules 4 Characteristics –Single assignment.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
Introduction to ML - Part 2 Kenny Zhu. What is next? ML has a rich set of structured values Tuples: (17, true, “stuff”) Records: {name = “george”, age.
CSE 130 : Winter 2006 Programming Languages Ranjit Jhala UC San Diego Lecture 6: Higher-Order Functions, Polymorphism.
CSE 130 : Winter 2006 Programming Languages Ranjit Jhala UC San Diego Lecture 7: Polymorphism.
CS 2104 : Prog. Lang. Concepts. Functional Programming I Lecturer : Dr. Abhik Roychoudhury School of Computing From Dr. Khoo Siau Cheng’s lecture notes.
Programovací jazyky F# a OCaml Chapter 5. Hiding recursion using function-as-values.
Scala Parallel Collections Aleksandar Prokopec EPFL.
An introduction to F# Bogdan Brinzarea-Iamandi Banca Romaneasca 22 February 2010.
PrasadCS7761 Haskell Data Types/ADT/Modules Type/Class Hierarchy Lazy Functional Language.
Patterns in OCaml functions. Formal vs. actual parameters Here's a function definition (in C): –int add (int x, int y) { return x + y; } –x and y are.
Chapter 9: Functional Programming in a Typed Language.
Functional Programming With examples in F#. Pure Functional Programming Functional programming involves evaluating expressions rather than executing commands.
A Third Look At ML Chapter NineModern Programming Languages, 2nd ed.1.
Scala Parallel Collections Aleksandar Prokopec EPFL.
CMSC 330: Organization of Programming Languages Maps and Folds Anonymous Functions.
CSE 130 : Spring 2011 Programming Languages Ranjit Jhala UC San Diego Lecture 6: Higher-Order Functions.
Kyung-Goo Doh Hanyang University - ERICAComputer Science & Engineering Functional Programming / Imperative Programming CSE215 Fundamentals of Program Design.
Introduction to Objective Caml. General comments ML is a purely functional language--there are (almost) no side effects There are two basic dialects of.
Haskell Chapter 5, Part II. Topics  Review/More Higher Order Functions  Lambda functions  Folds.
1 Objective Caml (Ocaml) Aaron Bloomfield CS 415 Fall 2005.
Functional Processing of Collections (Advanced) 6.0.
CS314 – Section 5 Recitation 9
CS314 – Section 5 Recitation 10
Types CSCE 314 Spring 2016.
ML: a quasi-functional language with strong typing
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Spring 2017.
Expanded Recursive Diagrams OCAML rapid tour, day 2
Functional Processing of Collections (Advanced)
CMSC 330: Organization of Programming Languages
Functional Programming
COS 260 DAY 10 Tony Gauvin.
Objective caml Daniel Jackson MIT Lab for Computer Science 6898: Advanced Topics in Software Design March 18, 2002.
Nicholas Shahan Spring 2016
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Spring 2013.
Agenda SML Docs First-Class Functions Examples Standard Basis
Agenda SML Docs First-Class Functions Examples Standard Basis
CSE 341 Section 5 Winter 2018.
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Autumn 2018.
Python Tutorial for C Programmer Boontee Kruatrachue Kritawan Siriboon
Fundamentals of Functional Programming
CSE-321 Programming Languages Introduction to Functional Programming
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Zach Tatlock Winter 2018.
Madhusudan Parthasarathy
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Spring 2016.
CSE 341 Lecture 2 lists and tuples; more functions; mutable state
PROGRAMMING IN HASKELL
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Spring 2019.
Brett Wortzman Summer 2019 Slides originally created by Dan Grossman
CSE341: Programming Languages Lecture 6 Nested Patterns Exceptions Tail Recursion Dan Grossman Autumn 2017.
Review Previously in: Lots of language features: functions, lists, records, tuples, variants, pattern matching Today: No new language features New idioms.
Presentation transcript:

F# Overview: Immutable Data + Pure Functions

Acknowledgements Authored by – Thomas Ball, MSR Redmond Includes content from the F# team

Functional Languages Focus on data – Immutability – Applicative data transformations map, filter, reduce, … Pure functions – can execute in parallel without interference

F#: Influences OCamlC#/.NET Similar core language Similar object model

Immutability is the Default in F# Immutable Lists! Immutable Records! Immutable Sets! Immutable Objects! Immutable Tuples! Immutable Dictionaries! Immutable Unions! + lots of language features to encourage immutability

Immutability the norm… Values may not be changed

Immutability the norm… Values may not be changed Data is immutable by default  Can’t Mutate Copy & Update

In Praise of Immutability Immutable objects can transfer between threads Immutable objects never have race conditions

Some Basic Types Basic Types/Literals int 76 string float 3.14, 3.2e5 char '7' bool true, false unit ()

Some Basic Operators Booleans not exprBoolean negation expr && exprBoolean “and” expr || exprBoolean “or” Booleans not exprBoolean negation expr && exprBoolean “and” expr || exprBoolean “or” Overloaded Arithmetic x + yAddition x - ySubtraction x * yMultiplication x / yDivision x % yRemainder/modulus -xUnary negation Overloaded Arithmetic x + yAddition x - ySubtraction x * yMultiplication x / yDivision x % yRemainder/modulus -xUnary negation

Tuples TupleType (1,2)int*int (1,2,3)int*int*int (1,2,3,4)int*int*int*int ((1,2),3)(int*int)*int (true,(2,3))bool*(int*int) TupleType (1,2)int*int (1,2,3)int*int*int (1,2,3,4)int*int*int*int ((1,2),3)(int*int)*int (true,(2,3))bool*(int*int)

Let Bindings (give names to values) 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

Lists []Empty list [x]One element list [x;y]Two element list hd::tlCons element hd on list tl list l2 to list l1 []Empty list [x]One element list [x;y]Two element list hd::tlCons element hd on list tl list l2 to list l1 length lnumber of elements in l map f lmap function f over l filter f lelements of l passing f zip l1 l2One list from two lists length lnumber of elements in l map f lmap function f over l filter f lelements of l passing f zip l1 l2One list from two lists

Recursive Polymorphic Data Types type 'a Tree = | Leaf of 'a | Node of 'a Tree list let tree0 = Leaf (1,2) let tree1 = Node [Leaf (2,3);Leaf (3,4)] let tree2 = Node [t0;t1]

Lambdas in F# let timesTwo = List.map (fun i -> i*2) [1;2;3;4] > let timesTwo = List.map (fun i -> i*2) [1;2;3;4];; val timesTwo : int list = [2; 4; 6; 8] > let timesTwo = List.map (fun i -> i*2) [1;2;3;4];; val timesTwo : int list = [2; 4; 6; 8] let sumPairs = List.map (fun (a,b) -> a+b) [(1,9);(2,8);(3,7)] > let sumPairs = List.map (fun (a,b) -> a+b) [(1,9);(2,8);(3,7)];; val sumPairs : int list = [10; 10; 10] > let sumPairs = List.map (fun (a,b) -> a+b) [(1,9);(2,8);(3,7)];; val sumPairs : int list = [10; 10; 10]

Function Application > let data = (1, 2, 3) ;; val data : int * int * int = (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) ;; val f : int * int * int -> int * int * int > let res = f data ;; val res : int * int * int = (7, 10, 15)

Function Currying > List.map ;; val it : (('a -> 'b) -> 'a list -> 'b list) > let timesTwoFun = List.map (fun i -> i*2) ;; val timesTwoFun : (int list -> int list) > timesTwoFun [1;2;3] ;; val it : int list = [2; 4; 6] > List.map ;; val it : (('a -> 'b) -> 'a list -> 'b list) > let timesTwoFun = List.map (fun i -> i*2) ;; val timesTwoFun : (int list -> int list) > timesTwoFun [1;2;3] ;; val it : int list = [2; 4; 6]

Functional– Pipelines x |> f The pipeline operator f x

Functional– Pipelines x |> f1 |> f2 |> f3 Successive stages in a pipeline f3 (f2 (f1 x))

Pattern Matching match expr with | pat -> expr … | pat -> expr

Matching Basic Values /// Truth table for AND via pattern matching let testAndExplicit x y = match x, y with | true, true -> true | true, false -> false | false, true -> false | false, false -> false Truth table > testAndExplicit true true;; true > testAndExplicit true true;; true

Wildcards /// Truth table for AND via pattern matching let testAnd x y = match x, y with | true, true -> true | _ -> false “Match anything” > testAnd true false;; false > testAnd true false;; false

Matching Structured Data let rec length l = match l with | [] -> 0 | _::tl -> 1+(length tl) A series of structured patterns > listLength [1;2;3] ;; 3 > listLength [1;2;3] ;; 3

Two Popular List Functions let rec map f l = match l with | [] -> [] | hd::tl -> (f hd)::(map f tl) let rec fold f acc l = match l with | [] -> acc | hd::tl -> (fold f (f acc hd) tl) ('a -> 'b) -> 'a list -> 'b list('a -> 'b -> 'a) -> 'a -> 'b list -> 'a “Aggregation”

Matching On a Tree let rec size t = match t with | Leaf _ -> 1 | Node l -> fold (fun a t -> a+(size t)) 1 l > size tree2 ;; 5 > size tree2 ;; 5 let tree0 = Leaf (1,2) let tree1 = Node [Leaf (2,3);Leaf (3,4)] let tree2 = Node [t0;t1]

Application: Compute Convex Hull

QuickHull, Pictorially p1=(x1,y2) p2=(x2,y2) p1-p2: split line pm let cross_product ((x1,y1),(x2,y2)) (xo,yo) = (x1-xo)*(y2-yo) - (y1-yo)*(x2-xo)

Points Above Line with Distance p1=(x1,y2) p2=(x2,y2) p1-p2: split line pm let accFun line ((pm,max),l) p = let cp = cross_product line p if (cp > 0.0) then ((if cp > max then (p,cp) else ((pm,max))), p::l) else ((pm,max),l) let aboveLineAndMax points line = points |> List.fold accFun (((0.0,0.0),0.0),[]) c>0.0

QuickHull let rec hsplit points (p1,p2) = let ((pm,_),aboveLine) = aboveLineAndMax points (p1,p2) match aboveLine with | [] | _::[] -> p1::aboveLine |> HullLeaf | _ -> [(p1,pm);(pm,p2)] |> List.map (hsplit aboveLine) |> HullNode let quickhull points = let minx = List.minBy (fun (x,_) -> x) points let maxx = List.maxBy (fun (x,_) -> x) points [(minx,maxx);(maxx,minx)] |> List.map (hsplit points) |> HullNode

Next Lecture Parallelizing QuickHull

Most of the computation takes place in aboveLineAndMax List.fold accFun seed ls – accFun: ‘Acc -> ‘S -> ‘Acc – seed: ‘Acc – ls: ‘S list let aboveLineAndMax points line = points |> List.fold accFun (((0.0,0.0),0.0),[])

Sequential Implementation of Fold let rec fold accFun seed ls = match ls with | [] -> seed | hd::tl -> (fold accFun (accFun seed hd) tl)

seed accFun … Parallel Aggregation Pattern seed accFun … … 34 mergeFun

Parallel Aggregation Implementation (using.NET Tasks) let rec foldPar accFun mergeFun seed listOfLists = let accL s l = l |> List.fold accFun s |> finalFun listOfLists |> List.map (fun ls -> Task.Factory.StartNew(accL seed ls)) |> List.map (fun task -> task.Result) |> List.fold mergeFun (finalFun seed)

Correctness? Parallel aggregation partitions the input and uses the same seed multiple times Parallel aggregation does not necessarily apply accFun in the same order as the sequential aggregation Parallel aggregation uses mergeFun to merge results from different partitions

Associativity/Commutativity of Operator F For all valid inputs x, y, z: – F(x,y) is associative if F(F(x,y),z) = F(x,F(y,z)) – F(x,y) is commutative if F(x,y) = F(y,x) For example, Max is commutative because – Max(x,y) = Max(y,x) And also associative because – Max(Max(x,y),z) = Max(x,Max(y,z))

Associativity/Commutativity Examples Associative NoYes Commutative No (a, b) => a / b (a, b) => a – b (a, b) => 2 * a + b (string a, string b) => a.Concat(b) (a, b) => a (a, b) => b Yes (float a, float b) => a + b (float a, float b) => a * b (bool a, bool b) => !(a && b) (int a, int b) => 2 + a * b (int a, int b) => (a + b) / 2 (int a, int b) => a + b (int a, int b) => a * b (a, b) => Min(a, b) (a, b) => Max(a, b)

Three Correctness Rules Let S=seed, F=accL, G=mergeFun 1. F(a, x) = G(a, F(S, x)) – for all possible accumulator values of a and all possible element values of x 2. G(a, b) = G(b, a) – for all possible values of a, b 3. G(G(a, b), c) = G(a, G(b, c)) – for all possible values of a, b, c

Something To Prove Given – list L = – seed, accFun, mergeFun obeying three rules Show List.fold accFun seed |> finalFun = foldPar accFun mergeFun seed [l1;…;lN]

Performance Concerns – accL should do enough computation to offset cost of coordination (fork/join of Tasks) – sublists of listOfLists should be of sufficient size and balanced let rec foldPar accFun finalFun mergeFun seed listOfLists = let accL s l = l |> List.fold accFun s listOfLists |> List.map (fun l -> Task.Factory.StartNew(accL seed l)) |> List.map (fun task -> task.Result) |> List.fold mergeFun (finalFun seed)

Returning to QuickHull let accFun line ((pm,max),(len,l)) p = let cp = cross_product line p if (cp > 0.0) then ((if cp > max then (p,cp) else ((pm,max))), (len+1,p::l)) else ((pm,max),(len,l)) let aboveLineAndMax points line = points |> List.fold accFun (((0.0,0.0),0.0),(0,[]))

finalFun and mergeFun for QuickHull? let mergeFun ((pm1,max1),(cnt1,l1)) ((pm2,max2),(cnt2,l2)) = ((if (max1 > max2) then (pm1,max1) else (pm2,max2)),

Correctness is associative but not commutative Doesn’t matter because we are treating list of lists as a set of lists (so we are as a union operator)

QuickHull Issues The size of the point sets can shrink considerably for each recursive call to hsplit Track size of output of aboveLineAndMax to determine – if parallelization of futures calls will be worthwhile – when to return to fully sequential processing

Where does the List of Lists (Partition) Come From? Static partition of initial list Dynamic partition