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
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
Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion Outline 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 3 / 53
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 = f1 >> f2 2 l e t h = f1 >> f2 >> f3 . . . • Function composition is associative 1 ( f1 >> f2 ) >> f3 ≡ f1 >> ( f2 >> f3 ) • Functions must be compatible! 1 f1 : ’ a1 − > ’ a2 2 f2 : ’ a2 − > ’ a3 3 f1 >> f2 : ’ a1 − > ’ a3 4 / 53
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 = f1 >> f2 2 l e t h = f1 >> f2 >> f3 . . . • Function composition is associative 1 ( f1 >> f2 ) >> f3 ≡ f1 >> ( f2 >> f3 ) • Functions must be compatible! 1 f1 : ’ a1 − > ’ a2 2 f2 : ’ a2 − > ’ a3 3 f1 >> f2 : ’ a1 − > ’ a3 4 / 53
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 = f1 >> f2 2 l e t h = f1 >> f2 >> f3 . . . • Function composition is associative 1 ( f1 >> f2 ) >> f3 ≡ f1 >> ( f2 >> f3 ) • Functions must be compatible! 1 f1 : ’ a1 − > ’ a2 2 f2 : ’ a2 − > ’ a3 3 f1 >> f2 : ’ a1 − > ’ a3 4 / 53
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 | > f1 2 l e t y = x | > f1 | > f2 . . . • Forward pipelines are left-associative 1 x | > f1 | > f2 ≡ ( x | > f1 ) | > f2 • Again, compatibility required! 5 / 53
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 | > f1 2 l e t y = x | > f1 | > f2 . . . • Forward pipelines are left-associative 1 x | > f1 | > f2 ≡ ( x | > f1 ) | > f2 • Again, compatibility required! 5 / 53
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 | > f1 2 l e t y = x | > f1 | > f2 . . . • Forward pipelines are left-associative 1 x | > f1 | > f2 ≡ ( x | > f1 ) | > f2 • Again, compatibility required! 5 / 53
Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion Composition vs Pipelines (F#) • Equivalent 1 y = x | > f1 | > f2 l e t 2 3 y = ( f1 >> f2 ) x l e t • Definitions? 6 / 53
Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion Composition vs Pipelines (F#) • Equivalent 1 y = x | > f1 | > f2 l e t 2 3 y = ( f1 >> f2 ) x l e t • Definitions? 6 / 53
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 ∗ y 2 3 l e t a = ( ∗ +) 3 4 4 l e t b = 3 ∗ + 4 5 6 printfn ”%d %d” a b // 25 25 7 / 53
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
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
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) ∗ y 2 3 l e t y = f (2+1) (6+1) 4 5 l e t z = 2+1 | > f < | 6+1 6 7 printfn ”%d %d” y z 9 / 53
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 ) 2 3 l e t h2 = 4 ( fun ( x : string ) − > x . Length ) >> 5 ( fun y − > ( double y )/2.0 ) 6 l e t r2 = h2 ”abc” // 1.5 7 8 l e t h3 = 9 ( fun ( x : string ) − > 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
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 x 2 3 l e t r1 = 4 ”abc” 5 | > fun x − > x . Length 6 7 r2 = l e t 8 ”abc” 9 | > fun x − > x . Length 10 | > fun y − > ( double y )/2.0 11 12 r3 = l e t 13 ”abc” 14 | > fun x − > x . Length 15 | > fun y − > ( double y )/2.0 16 | > fun z − > z +1.0 11 / 53
Comp (F#) Comp (C#) Comp (JS) IF LOOP Types Curry Ext (C#) Recursion Outline 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 12 / 53
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 < string , double > h2 = 2 H (( string x ) = > x . Length , y = > y / 2 . 0 ) ; 3 var r2 = h2 ( ”abc” ) ; // 1.5 4 5 Func < string , double > h3 = 6 H (H (( string x ) = > x . Length , y = > y /2.0) , 7 z = > z +1); 8 var r3 = h3 ( ”abc” ) ; // 2.5 13 / 53
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 < string , double > h2 = 2 H (( string x ) = > x . Length , y = > y / 2 . 0 ) ; 3 var r2 = h2 ( ”abc” ) ; // 1.5 4 5 Func < string , double > h3 = 6 H (H (( string x ) = > x . Length , y = > y /2.0) , 7 z = > z +1); 8 var r3 = h3 ( ”abc” ) ; // 2.5 13 / 53
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 f ( x ) ; return 3 } • Sample 1 var r1 = P ( ”abc” , x = > x . Length ) ; // 3 2 3 var r2 = P (P ( ”abc” , x = > x . Length ) , 4 y = > y / 2 . 0 ) ; // 1.5 5 6 var r3 = P (P (P ( ”abc” , x = > x . Length ) , 7 y = > y /2.0) , 8 z = > z +1); // 2.5 14 / 53
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 f ( x ) ; return 3 } • Sample 1 var r1 = P ( ”abc” , x = > x . Length ) ; // 3 2 3 var r2 = P (P ( ”abc” , x = > x . Length ) , 4 y = > y / 2 . 0 ) ; // 1.5 5 6 var r3 = P (P (P ( ”abc” , x = > x . Length ) , 7 y = > y /2.0) , 8 z = > z +1); // 2.5 14 / 53
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
Recommend
More recommend