functional programming part ii - computer science · comp (f#) comp (c#) comp (js) if loop types...

44
Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion Functional Programming – Part II Radu Nicolescu Department of Computer Science University of Auckland 12 Sept 2018 Updated 14 Sept 2018 1 / 53

Upload: others

Post on 31-May-2020

13 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Functional Programming – Part II

Radu NicolescuDepartment of Computer Science

University of Auckland

12 Sept 2018Updated 14 Sept 2018

1 / 53

Page 2: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

1 Composition and Pipelining (F#)

2 Composition and Pipelining (C#)

3 Composition and Pipelining (JS)

4 Composition IF

5 Composition LOOP

6 Composition and Types

7 Currying and Partial Application

8 Extension Methods (C#)

9 Recursion

2 / 53

Page 3: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Composition in a nutshell (F#)

• Forward composition (left-to-right)

1 l e t h = f 1 >> f 22 l e t h = f 1 >> f 2 >> f 3 . . .

• Function composition is associative

1 ( f 1 >> f 2 ) >> f 3 ≡ f 1 >> ( f 2 >> f 3 )

• Functions must be compatible!

1 f 1 : ’ a1 −> ’ a22 f 2 : ’ a2 −> ’ a33 f 1 >> f 2 : ’ a1 −> ’ a3

4 / 53

Page 4: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Pipelines in a nutshell (F#)

• Forward pipeline (left-to-right)

1 l e t y = x |> f 12 l e t y = x |> f 1 |> f 2 . . .

• Forward pipelines are left-associative

1 x |> f 1 |> f 2 ≡ ( x |> f 1 ) |> f 2

• Again, compatibility required!

5 / 53

Page 5: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Composition vs Pipelines (F#)

• Equivalent

1 l e t y = x |> f 1 |> f 223 l e t y = ( f 1 >> f 2 ) x

• Definitions?

6 / 53

Page 6: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Sidebar: operators (F#)

• Equivalent

1 l e t ( ∗+) x y = x∗x + y∗y23 l e t a = ( ∗+) 3 44 l e t b = 3 ∗+ 456 p r i n t f n ”%d %d” a b // 25 25

7 / 53

Page 7: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Composition and Pipelines: Definitions (F#)

• Forward composition (left-to-right)

1 l e t (>>) f g = fun x −> g ( f x )

• Forward pipeline (left-to-right)

1 l e t ( |>) x f = f x

• Reverse composition (right-to-left) – as in maths (f ◦ g)

1 l e t (<<) f g = fun x −> f ( g x )

• Reverse pipeline (right-to-left) – sometimes useful

1 l e t ( < |) f x = f x

8 / 53

Page 8: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Forward and Reverse Pipelines (F#)

• Avoiding extra parentheses

1 l e t f x y = ( x+1)∗y23 l e t y = f (2+1) (6+1)45 l e t z = 2+1 |> f <| 6+167 p r i n t f n ”%d %d” y z

9 / 53

Page 9: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Composition Samples (F#)

• Composition Samples (F#)

1 l e t (>>) f g = fun x −> g ( f x )23 l e t h2 =4 ( fun ( x : s t r i n g ) −> x . Length ) >>5 ( fun y −> ( double y ) / 2 . 0 )6 l e t r2 = h2 ” abc ” // 1 .578 l e t h3 =9 ( fun ( x : s t r i n g ) −> x . Length ) >>

10 ( fun y −> ( double y ) / 2 . 0 ) >>11 ( fun z −> z +1.0)12 l e t r3 = h3 ” abc ” // 2 .5

10 / 53

Page 10: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Pipeline Samples (F#)

• Pipeline Samples (F#)

1 l e t ( |>) x f = f x23 l e t r1 =4 ” abc ”5 |> fun x −> x . Length67 l e t r2 =8 ” abc ”9 |> fun x −> x . Length

10 |> fun y −> ( double y ) / 2 . 01112 l e t r3 =13 ” abc ”14 |> fun x −> x . Length15 |> fun y −> ( double y ) / 2 . 016 |> fun z −> z +1.0

11 / 53

Page 11: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Composition as high-order function (C#)

• More complicated than in F# /

• Forward composition (left-to-right) as high-order function

1 Func<A, C> H<A, B, C> ( Func<A, B> f , Func<B, C> g ) {2 return x => g ( f ( x ) ) ;3 }

• Sample

1 Func<s t r i n g , double> h2 =2 H ( ( s t r i n g x ) => x . Length , y => y / 2 . 0 ) ;3 var r2 = h2 ( ” abc ” ) ; // 1 . 545 Func<s t r i n g , double> h3 =6 H (H ( ( s t r i n g x ) => x . Length , y => y / 2 . 0 ) ,7 z => z +1);8 var r3 = h3 ( ” abc ” ) ; // 2 . 5

13 / 53

Page 12: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Pipeline as high-order function (C#)

• More complicated than in F# /

• Forward pipeline (left-to-right)

1 B P<A, B> (A x , Func<A, B> f ) {2 return f ( x ) ;3 }

• Sample

1 var r1 = P ( ” abc ” , x => x . Length ) ; // 323 var r2 = P (P ( ” abc ” , x => x . Length ) ,4 y => y / 2 . 0 ) ; // 1 . 556 var r3 = P (P (P ( ” abc ” , x => x . Length ) ,7 y => y / 2 . 0 ) ,8 z => z +1); // 2 . 5

14 / 53

Page 13: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Pipelines – A Better Solution (C#)

• Extension methods!

• At the end of this handout

15 / 53

Page 14: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Composition as high-order function (JS)

• Again, more complicated than in F# /

• Forward composition (left-to-right) as high-order function

1 funct ion H ( f , g ) { return x => g ( f ( x ) ) }

• Sample

1 l e t h2 =2 H ( x => x . l e n g t h , y => y / 2 . 0 )3 l e t r2 = h2 ( ” abc ” ) // 1 . 545 l e t h3 =6 H (H ( x => x . l e n g t h , y => y / 2 . 0 ) , z => z+1)7 l e t r3 = h3 ( ” abc ” ) // 2 . 5

17 / 53

Page 15: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Pipe/Composition as high-order function (JS)

• “Pipe” from ramda

• In fact, this “pipe” is a forward composition (left-to-right)

1 var R = r e q u i r e ( ’ ramda ’ )

• Sample

1 l e t p1 = R . p i p e ( x => x . l e n g t h )2 l e t r1 = p1 ( ” abc ” ) // 334 l e t p2 = R . p i p e ( x => x . l e n g t h , y => y / 2 . 0 )5 l e t r2 = p2 ( ” abc ” ) // 1 . 567 l e t p3 =8 R . p i p e ( x => x . l e n g t h , y => y / 2 . 0 , z => z+1)9 l e t r3 = p3 ( ” abc ” ) // 2 . 5

18 / 53

Page 16: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Pipe/Composition as high-order function (JS)

• “Pipe” custom definition

1 const p i p e = ( . . . f u n c s ) =>2 f u n c s . r e d u c e (3 ( acc , c u r r ) => x => c u r r ( acc ( x ) ) , i => i ) ;

• Will be discussed later (Array.reduce)

• Sample

1 l e t p3 =2 p i p e ( x => x . l e n g t h , y => y / 2 . 0 , z => z+1)3 l e t r 3 = p3 ( ” abc ” ) // 2 . 5

• Mozilla experimental feature: |> !

19 / 53

Page 17: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Composition IF (F#)

• IF as high-order function

1 l e t I f ( c , f , g ) =2 fun x −> i f c x then f x e l s e g x

• Sample

1 l e t h =2 I f (3 ( fun x −> x%2=1),4 ( fun x −> x +1) ,5 ( fun x −> 2∗x ) )67 l e t r10 = h 10 // 208 l e t r11 = h 11 // 12

21 / 53

Page 18: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Composition IF (C#)

• IF as high-order function

1 Func<A, B> I f <A, B> (2 Func<A, bool> c ,3 Func<A, B> f ,4 Func<A, B> g ) {5 return x => c ( x )? f ( x ) : g ( x ) ;6 }

• Sample

1 var h =2 I f (3 ( i n t x ) => x%2==1,4 ( i n t x ) => x+1,5 ( i n t x ) => 2∗x ) ;67 var r10 = h ( 1 0 ) ; // 208 var r11 = h ( 1 1 ) ; // 12

22 / 53

Page 19: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Composition IF (JS)

• IF as high-order function

1 funct ion I f ( c , f , g ) {2 return x => c ( x ) ? f ( x ) : g ( x )3 }

• Sample

1 l e t h =2 I f (3 ( x => x%2===1),4 ( x => x +1) ,5 ( x => 2∗x ) )67 l e t r10 = h ( 1 0 ) // 208 l e t r11 = h ( 1 1 ) // 11

23 / 53

Page 20: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Composition LOOP (F#)

• LOOP as high-order function – tail recursive!

1 l e t rec Loop ( c , f ) =2 fun x −> i f c ( x ) then Loop ( c , f ) ( f x ) e l s e x

• Sample

1 l e t h =2 Loop (3 ( fun x −> x < 100) ,4 ( fun x −> x + x ) )5 l e t r = h 10 // 160

• Equivalent

1 l e t mutable x ’ = 102 whi le ( x ’ < 100) do3 x ’ <− x ’ + x ’

25 / 53

Page 21: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Composition LOOP (C#)

• LOOP as high-order function

1 Func<A, A> Loop<A> (2 Func<A, bool> c ,3 Func<A, A> f ) {4 return x => c ( x )? Loop ( c , f ) ( f ( x ) ) : x ;5 }

• Sample

1 var h = Loop (2 ( i n t x ) => x < 100 ,3 ( i n t x ) => x + x ) ;4 var r = h ( 1 0 ) ; // 160

26 / 53

Page 22: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Composition LOOP (JS)

• LOOP as high-order function

1 funct ion Loop ( c , f ) {2 return x => c ( x ) ? Loop ( c , f ) ( f ( x ) ) : x3 }

• Sample

1 l e t h =2 Loop (3 ( x => x < 100) ,4 ( x => x + x ) )5 l e t r = h ( 1 0 ) // 160

27 / 53

Page 23: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

JS Composition is Type-less

• In JS you can get runtime type errors after inserting arbitraryobjects in a pipe

• Typical custom definition:

1 const p i p e = ( . . . f u n c s ) =>2 f u n c s . r e d u c e (3 ( acc , c u r r ) => x => c u r r ( acc ( x ) ) , i => i ) ;

• Sample wrong code...

1 l e t p3 = p i p e ( 7 , ” abc ” )2 l e t r 3 = p3 ( )

• ... which stops with runtime type error

1 // TypeEr ror : c u r r i s not a f u n c t i o n

29 / 53

Page 24: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

C# and F# Compositions are Type-aware

• NO runtime type errors: only compatible functions can becomposed

• Explicitly typed C# code:

1 Func<A, C> H<A, B, C> ( Func<A, B> f , Func<B, C> g ) {2 return x => g ( f ( x ) ) ;3 }

• Implicitly typed F# code:

1 l e t (>>) f g = fun x −> g ( f x )

• F# types are inferred and can be visualised, e.g. with FSI

1 > (>>);;2 ( ( ’ a −> ’ b ) −> ( ’ b −> ’ c ) −> ’ a −> ’ c )

30 / 53

Page 25: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

F# Composition with explicit types

• Implicitly typed F# code:

1 l e t (>>) f g = fun x −> g ( f x )

• Although not usual, F# types can be made explicit:

1 l e t (>>) ( f : ’ a−>’b ) ( g : ’ b−>’c ) : ’ a−>’c =2 fun x −> g ( f x )

31 / 53

Page 26: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

F# Compositions – Types Summary

• Forward (LR) composition:

1 l e t (>>) f g = fun x −> g ( f x )2 // ( ’ a−>’b ) −> ( ’ b−>’c ) −> ’ a −> ’ c

• Forward (LR) pipe:

1 l e t ( |>) x f = f x // ’ a −> ( ’ a−>’b ) −> ’ b

• IF:

1 l e t I f ( c , f , g ) =2 fun x −> i f c x then f x e l s e g x3 // c : ( ’ a−>bool )∗ f : ( ’ a−>’b )∗ g : ( ’ a−>’b ) −> x : ’ a −> ’ b

• LOOP:

1 l e t rec Loop ( c , f ) =2 fun x −> i f c ( x ) then Loop ( c , f ) ( f x ) e l s e x3 // c : ( ’ a−>bool )∗ f : ( ’ a−>’a ) −> x : ’ a −> ’ a

32 / 53

Page 27: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Currying

Programming technique inspired from mathematical logic,following ideas developed by Moses Schonfinkel and Haskell Curry.

Problem

Transform a function with n parameters into a chain of n functionswith one parameter each

34 / 53

Page 28: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Currying – Benefits

• Optimizations are possible by partial evaluation of functions

• Pipelining is straightforward with functions of one parameter

• Theoretical proofs are easier with functions of one parameter

35 / 53

Page 29: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Currying a function of two parameters

Given p : A× B → Cdetermine q : A→ (B → C )such that p(x , y) = q(x)(y)

36 / 53

Page 30: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Currying a function of two parameters (C#)

• Sample (where A = B = C = int):

1 Func<int , int , int> p = ( x , y ) => x∗x + y∗y ;2 Func<int , Func<int , int>> q = x => y => x∗x + y∗y ;3 Func<int , Func<int , int>> q2 = x => ( y => x∗x + y∗y ) ;

• Optimised equivalent for q(3)

1 Func<int , int> q ( 3 ) = y => 9 + y∗y ;2 // potentially faster than 3*3 + y*y

• Usage

1 var b = q ( 3 ) ( 4 ) ; // 252 var b2 = q2 ( 3 ) ( 4 ) ; // 2534 Func<int , int> r = q2 ( 3 ) ;5 var c1 = r ( 4 ) ; // 256 var c2 = r ( 5 ) ; // 34

37 / 53

Page 31: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Currying a function of two parameters (JS)

• Sample

1 l e t p = ( x , y ) => x∗x + y∗y23 l e t q = x => y => x∗x + y∗y4 l e t q2 = x => ( y => p ( x , y ) )

• Usage

1 l e t b = q ( 3 ) ( 4 )2 l e t b2 = q2 ( 3 ) ( 4 )34 l e t r = q ( 3 )5 l e t c1 = r ( 4 )6 l e t c2 = r ( 5 )

38 / 53

Page 32: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Currying a function of “two” parameters (F#)

• Sample

1 // p : i n t ∗ i n t −> i n t2 l e t p = fun ( x , y ) −> x∗x + y∗y34 // q : i n t −> i n t −> i n t5 l e t q = fun x −> fun y −> x∗x + y∗y6 l e t q ’ = fun x −> ( fun y −> p ( x , y ) )

• Usage

1 l e t b = q 3 42 l e t b ’ = q ’ 3 434 // r : i n t −> i n t5 l e t r = q 36 l e t c1 = r 47 l e t c2 = r 5

39 / 53

Page 33: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Currying a function of “two” parameters (F#)?

• All F# functions have one single parameter!

• This function has one single parameter, which is a tuple

1 // p : i n t ∗ i n t −> i n t2 l e t p = fun ( x , y ) −> x∗x + y∗y

• Example: function that returns a function (chained functions)

1 // q ’ ’ : i n t −> i n t −> i n t2 l e t q ’ ’ x y = x∗x + y∗y

• Equivalent function:

1 // q : i n t −> i n t −> i n t2 l e t q = fun x −> fun y −> x∗x + y∗y

40 / 53

Page 34: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Currying a function of three parameters (C#)

Given q : A× B × C → Ddetermine q1 : A→ (B → (C → D))such that q(x , y , z) = q1(x)(y)(z)

Example (where A = B = C = D = int):

1 Func<int , int , int , int>2 q = ( x , y , z ) => x∗x + y∗y + z∗ z ;

1 Func<int , Func<int , Func<int , int>>>2 q1 = x => ( y => ( z => x∗x + y∗y + z∗ z ) ) ;

1 q1 ( 1 0 ) ( 2 0 ) = z => 500 + z ;2 // potentially faster than 10*10 + 20*20 + z*z

41 / 53

Page 35: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Extension Methods in a Nutshell (C#)

• Retrofitting F#-style pipes in C#, an initially OO language

• F# pipeline of functions

1 s |> Foo |> Goo |> Hoo

• C# simulation via cascading/fluent method chaining

1 s . Foo ( ) . Goo ( ) . Hoo ( )

• It seems that we have to extend existing classes...but these may be sealed ( final in Java) /

• Extension methods come to the rescue ,

43 / 53

Page 36: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Extension Methods (C#)

An extension method:

• Is defined as a static method

• appears in a class decorated as static (see below)

• its first parameter is decorated with this

• despite being static, can also be can be called in instancenotation, where its first parameter appears as its target

A static class is equivalent to a sealed class with a privateconstructor: therefore, you can’t subclass it and you can’tinstantiate it! Its only purpose is to define extension methods.

44 / 53

Page 37: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Extension method (C#) – sample

Consider that we want to “extend” the (already sealed) System

class string with a new method bool Foo(int).

1 var b = ” abc ” . Foo ( 7 ) ; // ???

We cannot really extend class string, because it is sealed (whichcorresponds to final in Java)...

However, we can “emulate” such an extension as a static methodin a static class:

1 static c l a s s MyExtens ions {2 static bool Foo (this s t r i n g s , i n t i ) {3 . . .4 }5 }

45 / 53

Page 38: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Extension method (C#) – sample

We can invoke Foo either as a static method, or as an instancemethod for a string object!

1 s t r i n g s = ” abc ” ;23 var b1 = MyExtens ions . Foo ( s , 7 ) ; // static call45 var b2 = s . Foo ( 7 ) ; // ”instance”-like call

For the second version (instance-like call), the compiler will searchfor an appropriate method in all available static classes (this limitsthe scope of the search)

46 / 53

Page 39: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Extension method (C#) – sample

The instance notation is convenient for composing functions in afluent method chaining, i.e. cascading transformations (whichleads to crisp expressions) – similar to Unix-like pipelines

For example, besides Foo, assume a couple of other similarmethods, Goo and Hoo. Contrast the following two equivalentcalls, comparing them for expressiveness:

1 var b1 =2 MyExtens ions . Hoo (3 MyExtens ions . Goo (4 MyExtens ions . Foo ( s , 1 ) , 2 ) , 3 ) ;56 var b2 = s . Foo ( 1 ) . Goo ( 2 ) . Hoo ( 3 ) ;

Most functional elements in C# and LINQ are actually defined asextension methods!

47 / 53

Page 40: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Extension method (C#) – caveat

Caveat: in C#, extensions methods, such as Foo, are not realinstance methods:

• Cannot access private members

• Cannot be polymorphically overridden

48 / 53

Page 41: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Recursion in FP

Non-tail recursive factorial in F#:

1 l e t rec f a c t ( n : i n t ) =2 i f ( n <= 0) then 13 e l s e ( n ∗ f a c t ( n−1))

Tail recursive factorial in F#:

1 l e t rec f a c t t a i l r e c ( n : int , acc : i n t ) =2 i f ( n <= 0) then acc3 e l s e f a c t t a i l r e c ( n−1, n∗ acc )

50 / 53

Page 42: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Recursion in FP

Tail recursive factorial in F# – efficient! immutable values!

1 l e t rec f a c t t a i l r e c ( n : int , acc : i n t ) =2 i f ( n <= 0) then acc3 e l s e f a c t t a i l r e c ( n−1, n∗ acc )

Tail recursive factorial in F# – reverse engineered in C#:

1 p u b l i c s t a t i c i n t f a c t t a i l r e c ( i n t n , i n t acc ) {2 whi le ( n > 0) {3 i n t n1 = n − 1 ;4 acc = n ∗ acc ;5 n = n1 ;6 }7 return acc ;8 }

51 / 53

Page 43: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Recursion in FP

Why avoid recursion?

• Easy to define correct but inefficient algorithms (unless we usememoization or other optimisations)

1 // combinatorial explosion2 i n t Fib ( i n t n ) {3 i f ( n <= 1) return 1 ;4 return f i b ( n−1) + f i b ( n−2);5 }

• Inefficient implementations in non-FP languages, via actualcalls (even potential stack overflow)

52 / 53

Page 44: Functional Programming Part II - Computer Science · Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion 1 Composition and Pipelining (F#) 2 Composition and Pipelining

Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion

Recursion in FP

Why use recursion in FP?

• To define correct and efficient algorithms (via memoization orother optimisations)

• To use immutable values only (avoid changing the values ofvariables)

• Efficient implementation of tail calls, which are automaticallytransformed into loops

53 / 53