SlideShare a Scribd company logo
Making Your Program Spicy
Currying
and
Partial Function Application (PFA)
Dhaval Dalal
@softwareartisan
https://dhavaldalal.wordpress.com
14th Nov 2019
• Refers to the phenomena of rewriting a N-arg function
to a nest of functions, each taking only 1-arg at a time
Currying
// (String, Integer) -> String

String merge(String x, Integer y) {

return x + y.toString();

}

// String -> (Integer -> String)

Function<Integer, String> merge(String x) {

return y -> x + y.toString();

}

// () -> (String -> (Integer -> String))

Function<String, Function<Integer, String>> merge() {

return x -> y -> x + y.toString();

}
// (String -> (Integer -> String))

Function<String, Function<Integer, String>> merge = x -> y -> x + y.toString();

System.out.println(merge("Test#", 1)); // Test#1

System.out.println(merge("Test#").apply(2)); // Test#2

System.out.println(merge().apply("Test#").apply(3)); // Test#3
System.out.println(merge.apply("Test#").apply(4)); // Test#4
Currying
For each arg, there is
another nested function,
that takes a arg and
returns a function taking
the subsequent arg, until
all the args are exhausted.
f : (T, U, V) ↦ R
f′ : T ↦ U ↦ V ↦ R
f = f′
• Curried function is a nested structure, just like Russian
dolls, takes one arg at a time, instead of all the args at once.
Currying
• Function type associates towards right.
• In other words, arrow groups towards right.
Function<String, Function<Integer, String>> merge = 

x ->
y ->
x + y.toString();
x -> y -> x + y.toString();
// is same as
x -> (y -> x + y.toString());
• Function application associates towards left. In
other words, apply() groups towards left.
merge.apply("Test#").apply(1);
// is same as
(merge.apply("Test#")).apply(1);
Why Currying?
• Facilitates arguments to be applied from different
scopes.
Function<Integer, Function<Integer, Integer>> add =
x ->
y ->
x + y;
Function<Integer, Integer> increment = add.apply(1);
increment.apply(2); // 3
Function<Integer, Integer> decrement = add.apply(-1);
decrement.apply(2); // 1
• Helps us reshape and re-purpose the original function
by creating a partially applied function from it
Function<Integer, Function<Integer, Integer>> add =
x ->
y ->
x + y; Scope 1
Scope 2
But, how does that
make programming
spicier?
• Let’s say we have a Customer repository.
• Now, we want to allow authorised calls to repo. So,
Let’s write an authorise function.
class CustomerRepository {

Optional<Customer> findById(Integer id) {

return (id > 0) ? Optional.of(new Customer(id)) 

: Optional.empty();

} 

}
class Authoriser {

public Optional<Customer> authorise(CustomerRepository repo, Request
request) {

System.out.println("Authorizing Request#" + request.id);

// Some auth code here which guards the request.

// On success, the line below is executed.

return repo.findById(Integer.parseInt(request.get("customer_id")));

}

}
• We also have a Request.
• Lets see them in action…
class Request {

public final int id;

private Map<String, String> params = new HashMap<>();



Request(int id) { this.id = id; }

String set(String key, String value) { return params.put(key, value); } 

String get(String key) { return params.get(key); }

}
var authoriser = new Authoriser();

var repo = new CustomerRepository();



var request1 = new Request(1) {{ set("customer_id", "10"); }};



var customer1 = authoriser.authorise(repo, request1);

System.out.println(customer1);



var request2 = new Request(2) {{ set("customer_id", "30"); }};

var customer2 = authoriser.authorise(repo, request2);

System.out.println(customer2);
• Requests vary, however the CustomerRepository is
same.

• Can we avoid repeated injection of the repo?
Solution 1
Optional<Customer> authorise(Request req) {
CustomerRepository repo = new CustomerRepository();
return repo.findById(req.get());
}
Authoriser authoriser = new Authoriser();
Request req1 = new Request();
var customer1 = authoriser.authorise(req1);
Request req2 = new Request();
var customer2 = authoriser.authorise(req2);
• Wrap the authorise function in another function (also
called authorise)
• Requests vary, however the CustomerRepository is
same.

• Can we avoid repeated injection of the repo?
Solution 1
Optional<Customer> authorise(Request req) {
CustomerRepository repo = new CustomerRepository();
return repo.findById(req.get());
}
Authoriser authoriser = new Authoriser();
Request req1 = new Request();
var customer1 = authoriser.authorise(req1);
Request req2 = new Request();
var customer2 = authoriser.authorise(req2);
But
newification
locally like
this is
untestable!
• Wrap the authorise function in another function (also
called authorise)
Solution 2
class Authoriser {
public
Function<Request, Optional<Customer>> authorise(CustomerRepository repo) {
return req -> {
//Some auth code here which guards the request.
repo.findById(req.get());
}
}
}
var repo = new CustomerRepository();
Function<Request, Optional<Customer>> curriedAuthorise = authorise(repo);
Request req1 = new Request();
var customer1 = curriedAuthorise.apply(req1);
Request req2 = new Request();
var customer2 = curriedAuthorise.apply(req2);
• Re-shape authorise to accept only one fixed
parameter - CustomerRepository
Need some more
spice?
interface Transaction { }
interface ApprovalStrategy {
boolean approve(List<Transaction> ts);
//…
}
class Clearing {
private final ApprovalStrategy as;
Clearing(ApprovalStrategy as) {
this.as = as;
}
public boolean approve(List<Transaction> ts) {
return as.approve(ts);
}
}
//main
ApprovalStrategy singleMakerChecker = new SingleMakerChecker();
Clearing clearing = new Clearing(singleMakerChecker);
clearing.approve(ts);
Regular DI
Curried DI
interface Transaction { }
interface ApprovalStrategy {
boolean approve(List<Transaction> ts);
//…
}
class Clearing {
public
Function<List<Transaction>, Boolean> approve(ApprovalStrategy as) {
return ts -> as.approve(ts);
}
}
//main
Clearing clearing = new Clearing();
// ApprovalStrategy can now be injected from different contexts,
// one for production and a different one - say mock for testing,
// Just like in case of Regular DI.
clearing.approve(new SingleMakerChecker()).apply(ts);
Making Our Own Curry
<T, U, R>
Function<T, Function<U, R>> curry(BiFunction<T, U, R> fn) {
return t -> u -> fn.apply(t, u);
}
// Function with all args applied at the same time.
BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y;
// Curried Function - one arg at a time.
Function<Integer, Function<Integer, Integer>> cAdd = curry(add);
Function<Integer, Integer> increment = cAdd.apply(1);
increment.apply(2); // 3
Function<Integer, Integer> decrement = cAdd.apply(-1);
decrement.apply(2); // 1
It would be nice if
Java8 provided this
out-of-box on
BiFunction
Scala calls
this curried
Uncurry or Tuple it!
<T, U, R>
BiFunction<T, U, R> uncurry(Function<T, Function<U, R>> fn) {
return (t, u) -> fn.apply(t).apply(u);
}
// Curried Function - one arg at a time.
Function<Integer, Function<Integer, Integer>> add = x -> y -> x + y;
// Function with all args applied at the same time.
BiFunction<Integer, Integer, Integer> ucAdd = uncurry(add);
ucAdd.apply(2, 3); // 5
It would be nice if
Java8 provided this
out-of-box on
Function
Scala calls
this uncurried
Currying in Scala
scala> def merge1(x: String, y: Int) = x + y.toString
merge1: (x: String, y: Int)String
scala> val merge1F = merge1 _
merge1F: (String, Int) => String
scala> def merge2(x: String)(y: Int) = x + y.toString

scala> val merge2F = merge2 _
merge2F: String => (Int => String)
scala> val mergeTest = merge2F("Test#")
mergeTest: Int => String
scala> mergeTest(1)
res1: Test#1
scala> mergeTest(2)
res2: Test#2
• Scala uses special syntax for currying - It does not use
tupled arguments, instead uses multiple function call
syntax in the definition to denote a curried function.
Curry Uncurry
scala> def merge1(x: String, y: Int) = x + y.toString
merge1: (x: String, y: Int)String
scala> val merge1F = merge1 _
merge1F: (String, Int) => String
scala> val merge1FCurried = merge1F.curried
merge1FCurried: String => (Int => String)
scala> def merge2(x: String)(y: Int) = x + y.toString

scala> val merge2F = merge2 _
merge2F: String => (Int => String)
scala> val merge2FUncurried = Function.uncurried(merge2F)
merge2FUncurried: (String, Int) => String
Scala
PFA in Scala
// Partially Applied Function or Partial Function Application (PFA)

def greet(salutation: String, fname: String, lname: String)
= s"$salutation. $fname $lname"

println(greet("Mr", "Dhaval", "Dalal")) // Mr Dhaval Dalal
def new_ms = greet("Ms", _: String, _: String)
// (String, String) => String

println(new_ms("Ada", "Lovelace")) // Ms Ada Lovelace



def new_drew = greet(_: String, _: String, "Drew")

(String, String) => String
println(new_drew("Ms", "Nancy")) // Ms Nancy Drew
• Supply a value to partially apply the function and to
leave out the arguments unapplied, use underscore “_”

• Note: PFA is different from Partial Function
Re-shaping Third Party
Library Functions
• In third-party libraries we may never be able to
modify the code. 

• Use Currying/PFA to simplify the callers interface.
def power(n: Double) = Math.pow(_: Double, n)

val square = power(2)

println(square(2)) // 4.0



val cube = power(3)

println(cube(2)) // 8.0
Currying in Haskell
greet :: String -> String -> String -> String

greet salutation fname lname = salutation ++ ". " ++ fname ++ " " ++ lname



main :: IO ()

main = do

print $ greet "Mr" "Dhaval" "Dalal" -- Mr Dhaval Dalal

let greet_mr = greet "Mr"

print (greet_mr "Joe" "Shmo") -- Mr Joe Shmo

let greet_mr_joe = greet "Mr" "Joe"

print (greet_mr_joe "Sober") -- Mr Joe Sober

print "Done!"
• In Haskell, all the functions are curried by default,
you don’t need special syntax for that.

• It does not have Partially Applied Functions.
Currying in Haskell
Prelude> :type (*)
(*) :: Num a => a -> a -> a
Prelude> multiply2 = (*2)
Prelude> :type multiply2
multiplyBy2 :: Num a => a -> a
Prelude> multiply2 3
6
• Even operators are
curried by default.
Prelude> :type filter
filter :: (a -> Bool) -> [a] -> [a]
Prelude> even = x -> x `mod` 2 == 0
Prelude> filterEvens = filter even
Prelude> :type filterEvens
filterEvens :: Integral a => [a] -> [a]
Prelude> filterEvens [0..10]
[2,4,6,8,10]
Prelude> filterOdds = filter (not . even)
Prelude> filterOdds [0..10]
[1,3,5,7,9]
• Yet another
example…
PFA in Clojure
(defn new-person [salutation f-name l-name]

(println salutation f-name l-name))



(new-person "Mr." "Dhaval" "Dalal") ; Mr Dhaval Dalal
(def new-ms (partial new-person "Ms"))

(new-ms "Ada" "Lovelace") ; Ms Ada Lovelace
• Lets partially apply title to this function…
• Lets now partially apply title and first-name
(def new-ms-ada (partial new-person "Ms" "Ada"))

(new-ms-ada "Lovelace") ; Ms Ada Lovelace
PFA in Clojure
• What if we want to fix the third arg - last name
instead of the 1st?
(def new-dalal (partial new-person salutation f-name "Dalal"))

(new-dalal "Mr" “Dhaval")
; The above code won't compile
• This is because we need placeholder for 1st and 2nd
args, which we don’t want to apply., we can’t directly
apply the 3rd argument. 

• In Clojure, with partial function application the order of
arguments matters. Its from left to right. This is just
like currying.

• So, what do we do?
Lambda to the rescue
• We wrap this in a lambda!
(def new-dalal (fn [sal fname]

(new-person sal fname "Dalal")))
(new-dalal "Mr." "Dhaval") ; Mr. Dhaval Dalal
• Doing this by hand every time is tedious!

• Fortunately, Clojure has a macro to synthesise this
kind of "ad-hoc" partial function application
(def new-dalal #(new-person %1 %2 "Dalal")) ; Mr. Dhaval Dalal

(new-dalal "Mr." "Dhaval") ; Mr. Dhaval Dalal
(def new-ada #(new-person %1 "Ada" %2))

(new-ada "Ms." "Lovelace") ; Ms Ada Lovelace

(new-ada "Mrs." "???") ; Mrs. Ada ???
Currying in Groovy
def filterList = { filter, list -> list.findAll(filter) }

def even = { it % 2 == 0 }

def evens = filterList.curry(even)

println evens(0..10) // [0, 2, 4, 6, 8, 10]



def not = { !it }

def odds = filterList.curry(even >> not) // even andThen not

println odds(0..10) // [1, 3, 5, 7, 9]
• In Groovy, we need to explicitly call the curry
method on closure!
• It curries from left to right
def merge = { x, y, z ->

println "arg0: x = $x"

println "arg1: y = $y"

println "arg2: z = $z"

"$x$y$z"

}

println merge.curry(10)('Hello', new Date()) // 10Hello<Date>

println merge.curry(10, 'Hello')(new Date()) // 10Hello<Date>
Currying in Groovy
• And if you need to curry from right-to-left, use rcurry()
def merge = { x, y, z ->

println "arg0: x = $x"

println "arg1: y = $y"

println "arg2: z = $z"

"$x$y$z"

}

println merge.rcurry(10)('Hello', new Date()) // Hello<Date>10

println merge.rcurry(10, 'Hello')(new Date()) // <Date>10Hello
• And for currying at a index, use ncurry()
println merge.ncurry(1, new Date())(10, 'Hello') //10<Date>Hello

println merge.ncurry(0, new Date(), 'Hello')(10) //<Date>Hello10
Reflections
• You curry strictly from left-to-right.

• We don’t have to provide all the arguments to the
function at one go! This is partially applying the function. 

• In other words, Currying enables Partial Function
Application, a.k.a - Partially Applied Function (PFA).

• "ad-hoc PFA" is practically more powerful than currying
in some ways. With currying, you have to curry strictly from
left to right, with PFA you can do ad-hoc application of args

• In a language that deals well with PFA, you won’t really
miss currying, because you’ll use PFA where you would
have used currying.
References
• Code Jugalbandi (http://codejugalbandi.org)

• Exploring Functional Programming - Ryan Lemmer and
Dhaval Dalal

• https://github.com/CodeJugalbandi/FunctionalProgramming/
tree/master/melodies/currying

• Healthy Code Magazine Code Jugalbandi Article 

• https://www.slideshare.net/DhavalDalal/3-code-
jugalbandicurryingpfahealthycodemagazinemar2015
Thank - You!
https://github.com/DhavalDalal/FunctionalConference-2019-Currying-PFA-Demo

More Related Content

PDF
Creating Lazy stream in CSharp
PDF
DRYing to Monad in Java8
PPTX
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
PDF
FP in Java - Project Lambda and beyond
PDF
OOP and FP - Become a Better Programmer
PDF
Jumping-with-java8
PDF
From object oriented to functional domain modeling
PDF
Java 8 Workshop
Creating Lazy stream in CSharp
DRYing to Monad in Java8
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
FP in Java - Project Lambda and beyond
OOP and FP - Become a Better Programmer
Jumping-with-java8
From object oriented to functional domain modeling
Java 8 Workshop

What's hot (20)

PDF
JavaScript Functions
PDF
Laziness, trampolines, monoids and other functional amenities: this is not yo...
PDF
Lambdas and Streams Master Class Part 2
PDF
Booting into functional programming
PPT
Swiss army knife Spring
PPTX
LinkedIn TBC JavaScript 100: Functions
PDF
If You Think You Can Stay Away from Functional Programming, You Are Wrong
PDF
Functional Javascript
PDF
Pragmatic functional refactoring with java 8
PDF
Lambda and Stream Master class - part 1
PPTX
Java 7, 8 & 9 - Moving the language forward
PDF
Refactoring to Java 8 (Devoxx BE)
PDF
Object Design - Part 1
PPT
JavaScript Functions
PDF
Reactive Programming for a demanding world: building event-driven and respons...
PDF
Leveraging Completable Futures to handle your query results Asynchrhonously
PPTX
Java script advance-auroskills (2)
PPTX
Clean code slide
PDF
Sneaking inside Kotlin features
PDF
Java9 Beyond Modularity - Java 9 más allá de la modularidad
JavaScript Functions
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Lambdas and Streams Master Class Part 2
Booting into functional programming
Swiss army knife Spring
LinkedIn TBC JavaScript 100: Functions
If You Think You Can Stay Away from Functional Programming, You Are Wrong
Functional Javascript
Pragmatic functional refactoring with java 8
Lambda and Stream Master class - part 1
Java 7, 8 & 9 - Moving the language forward
Refactoring to Java 8 (Devoxx BE)
Object Design - Part 1
JavaScript Functions
Reactive Programming for a demanding world: building event-driven and respons...
Leveraging Completable Futures to handle your query results Asynchrhonously
Java script advance-auroskills (2)
Clean code slide
Sneaking inside Kotlin features
Java9 Beyond Modularity - Java 9 más allá de la modularidad
Ad

Similar to Currying and Partial Function Application (PFA) (20)

PPTX
Introduction to nsubstitute
ODP
Finagle and Java Service Framework at Pinterest
PPT
25-functions.ppt
PDF
Cocoa heads 09112017
PDF
What is new in java 8 concurrency
PDF
Celery with python
PPTX
Part 3-functions1-120315220356-phpapp01
PPTX
Столпы функционального программирования для адептов ООП, Николай Мозговой
PPT
Php Reusing Code And Writing Functions
PPTX
php user defined functions
PDF
Functional programming 101
ODP
From object oriented to functional domain modeling
PPTX
Function & Recursion
PPTX
Licão 13 functions
PPTX
Thinking Functionally with JavaScript
PPT
Test driven development_for_php
PPTX
Classes function overloading
PPT
Fp201 unit5 1
PPTX
Tools for Making Machine Learning more Reactive
PPTX
Function C++
Introduction to nsubstitute
Finagle and Java Service Framework at Pinterest
25-functions.ppt
Cocoa heads 09112017
What is new in java 8 concurrency
Celery with python
Part 3-functions1-120315220356-phpapp01
Столпы функционального программирования для адептов ООП, Николай Мозговой
Php Reusing Code And Writing Functions
php user defined functions
Functional programming 101
From object oriented to functional domain modeling
Function & Recursion
Licão 13 functions
Thinking Functionally with JavaScript
Test driven development_for_php
Classes function overloading
Fp201 unit5 1
Tools for Making Machine Learning more Reactive
Function C++
Ad

More from Dhaval Dalal (20)

PDF
Sri-Aurobindos-Integral-Education-Principles.pdf
PDF
Test Pyramid in Microservices Context
PDF
Code Retreat
PDF
Json Viewer Stories
PDF
Value Objects
PDF
Mars rover-extension
PDF
How Is Homeopathy Near To Yoga?
PDF
Approaching ATDD/BDD
PDF
Paradigms Code jugalbandi
PDF
Data Reconciliation
PDF
CodeRetreat
PDF
4-Code-Jugalbandi-destructuring-patternmatching-healthycode#apr2015
PDF
3-CodeJugalbandi-currying-pfa-healthycodemagazine#mar2015
PDF
CodeJugalbandi-Sequencing-HealthyCode-Magazine-Feb-2015
PDF
CodeJugalbandi-Expression-Problem-HealthyCode-Magazine#Jan-2015-Issue
PDF
The tao-of-transformation-workshop
PDF
Grooming with Groovy
PDF
Language portfolio
PDF
Code jugalbandi
PDF
A case-for-graph-db
Sri-Aurobindos-Integral-Education-Principles.pdf
Test Pyramid in Microservices Context
Code Retreat
Json Viewer Stories
Value Objects
Mars rover-extension
How Is Homeopathy Near To Yoga?
Approaching ATDD/BDD
Paradigms Code jugalbandi
Data Reconciliation
CodeRetreat
4-Code-Jugalbandi-destructuring-patternmatching-healthycode#apr2015
3-CodeJugalbandi-currying-pfa-healthycodemagazine#mar2015
CodeJugalbandi-Sequencing-HealthyCode-Magazine-Feb-2015
CodeJugalbandi-Expression-Problem-HealthyCode-Magazine#Jan-2015-Issue
The tao-of-transformation-workshop
Grooming with Groovy
Language portfolio
Code jugalbandi
A case-for-graph-db

Recently uploaded (20)

PPTX
ai tools demonstartion for schools and inter college
PDF
Digital Strategies for Manufacturing Companies
PDF
How Creative Agencies Leverage Project Management Software.pdf
PPTX
CHAPTER 12 - CYBER SECURITY AND FUTURE SKILLS (1) (1).pptx
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
AI in Product Development-omnex systems
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PPTX
Introduction to Artificial Intelligence
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
PPTX
ISO 45001 Occupational Health and Safety Management System
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Navsoft: AI-Powered Business Solutions & Custom Software Development
PPT
Introduction Database Management System for Course Database
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
ai tools demonstartion for schools and inter college
Digital Strategies for Manufacturing Companies
How Creative Agencies Leverage Project Management Software.pdf
CHAPTER 12 - CYBER SECURITY AND FUTURE SKILLS (1) (1).pptx
2025 Textile ERP Trends: SAP, Odoo & Oracle
Design an Analysis of Algorithms I-SECS-1021-03
AI in Product Development-omnex systems
Design an Analysis of Algorithms II-SECS-1021-03
Introduction to Artificial Intelligence
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
ISO 45001 Occupational Health and Safety Management System
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
How to Choose the Right IT Partner for Your Business in Malaysia
VVF-Customer-Presentation2025-Ver1.9.pptx
Navsoft: AI-Powered Business Solutions & Custom Software Development
Introduction Database Management System for Course Database
Odoo POS Development Services by CandidRoot Solutions
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...

Currying and Partial Function Application (PFA)

  • 1. Making Your Program Spicy Currying and Partial Function Application (PFA) Dhaval Dalal @softwareartisan https://dhavaldalal.wordpress.com 14th Nov 2019
  • 2. • Refers to the phenomena of rewriting a N-arg function to a nest of functions, each taking only 1-arg at a time Currying // (String, Integer) -> String
 String merge(String x, Integer y) {
 return x + y.toString();
 }
 // String -> (Integer -> String)
 Function<Integer, String> merge(String x) {
 return y -> x + y.toString();
 }
 // () -> (String -> (Integer -> String))
 Function<String, Function<Integer, String>> merge() {
 return x -> y -> x + y.toString();
 } // (String -> (Integer -> String))
 Function<String, Function<Integer, String>> merge = x -> y -> x + y.toString();
 System.out.println(merge("Test#", 1)); // Test#1
 System.out.println(merge("Test#").apply(2)); // Test#2
 System.out.println(merge().apply("Test#").apply(3)); // Test#3 System.out.println(merge.apply("Test#").apply(4)); // Test#4
  • 3. Currying For each arg, there is another nested function, that takes a arg and returns a function taking the subsequent arg, until all the args are exhausted. f : (T, U, V) ↦ R f′ : T ↦ U ↦ V ↦ R f = f′ • Curried function is a nested structure, just like Russian dolls, takes one arg at a time, instead of all the args at once.
  • 4. Currying • Function type associates towards right. • In other words, arrow groups towards right. Function<String, Function<Integer, String>> merge = 
 x -> y -> x + y.toString(); x -> y -> x + y.toString(); // is same as x -> (y -> x + y.toString()); • Function application associates towards left. In other words, apply() groups towards left. merge.apply("Test#").apply(1); // is same as (merge.apply("Test#")).apply(1);
  • 5. Why Currying? • Facilitates arguments to be applied from different scopes. Function<Integer, Function<Integer, Integer>> add = x -> y -> x + y; Function<Integer, Integer> increment = add.apply(1); increment.apply(2); // 3 Function<Integer, Integer> decrement = add.apply(-1); decrement.apply(2); // 1 • Helps us reshape and re-purpose the original function by creating a partially applied function from it Function<Integer, Function<Integer, Integer>> add = x -> y -> x + y; Scope 1 Scope 2
  • 6. But, how does that make programming spicier?
  • 7. • Let’s say we have a Customer repository. • Now, we want to allow authorised calls to repo. So, Let’s write an authorise function. class CustomerRepository {
 Optional<Customer> findById(Integer id) {
 return (id > 0) ? Optional.of(new Customer(id)) 
 : Optional.empty();
 } 
 } class Authoriser {
 public Optional<Customer> authorise(CustomerRepository repo, Request request) {
 System.out.println("Authorizing Request#" + request.id);
 // Some auth code here which guards the request.
 // On success, the line below is executed.
 return repo.findById(Integer.parseInt(request.get("customer_id")));
 }
 }
  • 8. • We also have a Request. • Lets see them in action… class Request {
 public final int id;
 private Map<String, String> params = new HashMap<>();
 
 Request(int id) { this.id = id; }
 String set(String key, String value) { return params.put(key, value); } 
 String get(String key) { return params.get(key); }
 } var authoriser = new Authoriser();
 var repo = new CustomerRepository();
 
 var request1 = new Request(1) {{ set("customer_id", "10"); }};
 
 var customer1 = authoriser.authorise(repo, request1);
 System.out.println(customer1);
 
 var request2 = new Request(2) {{ set("customer_id", "30"); }};
 var customer2 = authoriser.authorise(repo, request2);
 System.out.println(customer2);
  • 9. • Requests vary, however the CustomerRepository is same. • Can we avoid repeated injection of the repo? Solution 1 Optional<Customer> authorise(Request req) { CustomerRepository repo = new CustomerRepository(); return repo.findById(req.get()); } Authoriser authoriser = new Authoriser(); Request req1 = new Request(); var customer1 = authoriser.authorise(req1); Request req2 = new Request(); var customer2 = authoriser.authorise(req2); • Wrap the authorise function in another function (also called authorise)
  • 10. • Requests vary, however the CustomerRepository is same. • Can we avoid repeated injection of the repo? Solution 1 Optional<Customer> authorise(Request req) { CustomerRepository repo = new CustomerRepository(); return repo.findById(req.get()); } Authoriser authoriser = new Authoriser(); Request req1 = new Request(); var customer1 = authoriser.authorise(req1); Request req2 = new Request(); var customer2 = authoriser.authorise(req2); But newification locally like this is untestable! • Wrap the authorise function in another function (also called authorise)
  • 11. Solution 2 class Authoriser { public Function<Request, Optional<Customer>> authorise(CustomerRepository repo) { return req -> { //Some auth code here which guards the request. repo.findById(req.get()); } } } var repo = new CustomerRepository(); Function<Request, Optional<Customer>> curriedAuthorise = authorise(repo); Request req1 = new Request(); var customer1 = curriedAuthorise.apply(req1); Request req2 = new Request(); var customer2 = curriedAuthorise.apply(req2); • Re-shape authorise to accept only one fixed parameter - CustomerRepository
  • 13. interface Transaction { } interface ApprovalStrategy { boolean approve(List<Transaction> ts); //… } class Clearing { private final ApprovalStrategy as; Clearing(ApprovalStrategy as) { this.as = as; } public boolean approve(List<Transaction> ts) { return as.approve(ts); } } //main ApprovalStrategy singleMakerChecker = new SingleMakerChecker(); Clearing clearing = new Clearing(singleMakerChecker); clearing.approve(ts); Regular DI
  • 14. Curried DI interface Transaction { } interface ApprovalStrategy { boolean approve(List<Transaction> ts); //… } class Clearing { public Function<List<Transaction>, Boolean> approve(ApprovalStrategy as) { return ts -> as.approve(ts); } } //main Clearing clearing = new Clearing(); // ApprovalStrategy can now be injected from different contexts, // one for production and a different one - say mock for testing, // Just like in case of Regular DI. clearing.approve(new SingleMakerChecker()).apply(ts);
  • 15. Making Our Own Curry <T, U, R> Function<T, Function<U, R>> curry(BiFunction<T, U, R> fn) { return t -> u -> fn.apply(t, u); } // Function with all args applied at the same time. BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y; // Curried Function - one arg at a time. Function<Integer, Function<Integer, Integer>> cAdd = curry(add); Function<Integer, Integer> increment = cAdd.apply(1); increment.apply(2); // 3 Function<Integer, Integer> decrement = cAdd.apply(-1); decrement.apply(2); // 1 It would be nice if Java8 provided this out-of-box on BiFunction Scala calls this curried
  • 16. Uncurry or Tuple it! <T, U, R> BiFunction<T, U, R> uncurry(Function<T, Function<U, R>> fn) { return (t, u) -> fn.apply(t).apply(u); } // Curried Function - one arg at a time. Function<Integer, Function<Integer, Integer>> add = x -> y -> x + y; // Function with all args applied at the same time. BiFunction<Integer, Integer, Integer> ucAdd = uncurry(add); ucAdd.apply(2, 3); // 5 It would be nice if Java8 provided this out-of-box on Function Scala calls this uncurried
  • 17. Currying in Scala scala> def merge1(x: String, y: Int) = x + y.toString merge1: (x: String, y: Int)String scala> val merge1F = merge1 _ merge1F: (String, Int) => String scala> def merge2(x: String)(y: Int) = x + y.toString
 scala> val merge2F = merge2 _ merge2F: String => (Int => String) scala> val mergeTest = merge2F("Test#") mergeTest: Int => String scala> mergeTest(1) res1: Test#1 scala> mergeTest(2) res2: Test#2 • Scala uses special syntax for currying - It does not use tupled arguments, instead uses multiple function call syntax in the definition to denote a curried function.
  • 18. Curry Uncurry scala> def merge1(x: String, y: Int) = x + y.toString merge1: (x: String, y: Int)String scala> val merge1F = merge1 _ merge1F: (String, Int) => String scala> val merge1FCurried = merge1F.curried merge1FCurried: String => (Int => String) scala> def merge2(x: String)(y: Int) = x + y.toString
 scala> val merge2F = merge2 _ merge2F: String => (Int => String) scala> val merge2FUncurried = Function.uncurried(merge2F) merge2FUncurried: (String, Int) => String Scala
  • 19. PFA in Scala // Partially Applied Function or Partial Function Application (PFA)
 def greet(salutation: String, fname: String, lname: String) = s"$salutation. $fname $lname"
 println(greet("Mr", "Dhaval", "Dalal")) // Mr Dhaval Dalal def new_ms = greet("Ms", _: String, _: String) // (String, String) => String
 println(new_ms("Ada", "Lovelace")) // Ms Ada Lovelace
 
 def new_drew = greet(_: String, _: String, "Drew")
 (String, String) => String println(new_drew("Ms", "Nancy")) // Ms Nancy Drew • Supply a value to partially apply the function and to leave out the arguments unapplied, use underscore “_” • Note: PFA is different from Partial Function
  • 20. Re-shaping Third Party Library Functions • In third-party libraries we may never be able to modify the code. • Use Currying/PFA to simplify the callers interface. def power(n: Double) = Math.pow(_: Double, n)
 val square = power(2)
 println(square(2)) // 4.0
 
 val cube = power(3)
 println(cube(2)) // 8.0
  • 21. Currying in Haskell greet :: String -> String -> String -> String
 greet salutation fname lname = salutation ++ ". " ++ fname ++ " " ++ lname
 
 main :: IO ()
 main = do
 print $ greet "Mr" "Dhaval" "Dalal" -- Mr Dhaval Dalal
 let greet_mr = greet "Mr"
 print (greet_mr "Joe" "Shmo") -- Mr Joe Shmo
 let greet_mr_joe = greet "Mr" "Joe"
 print (greet_mr_joe "Sober") -- Mr Joe Sober
 print "Done!" • In Haskell, all the functions are curried by default, you don’t need special syntax for that. • It does not have Partially Applied Functions.
  • 22. Currying in Haskell Prelude> :type (*) (*) :: Num a => a -> a -> a Prelude> multiply2 = (*2) Prelude> :type multiply2 multiplyBy2 :: Num a => a -> a Prelude> multiply2 3 6 • Even operators are curried by default. Prelude> :type filter filter :: (a -> Bool) -> [a] -> [a] Prelude> even = x -> x `mod` 2 == 0 Prelude> filterEvens = filter even Prelude> :type filterEvens filterEvens :: Integral a => [a] -> [a] Prelude> filterEvens [0..10] [2,4,6,8,10] Prelude> filterOdds = filter (not . even) Prelude> filterOdds [0..10] [1,3,5,7,9] • Yet another example…
  • 23. PFA in Clojure (defn new-person [salutation f-name l-name]
 (println salutation f-name l-name))
 
 (new-person "Mr." "Dhaval" "Dalal") ; Mr Dhaval Dalal (def new-ms (partial new-person "Ms"))
 (new-ms "Ada" "Lovelace") ; Ms Ada Lovelace • Lets partially apply title to this function… • Lets now partially apply title and first-name (def new-ms-ada (partial new-person "Ms" "Ada"))
 (new-ms-ada "Lovelace") ; Ms Ada Lovelace
  • 24. PFA in Clojure • What if we want to fix the third arg - last name instead of the 1st? (def new-dalal (partial new-person salutation f-name "Dalal"))
 (new-dalal "Mr" “Dhaval") ; The above code won't compile • This is because we need placeholder for 1st and 2nd args, which we don’t want to apply., we can’t directly apply the 3rd argument. • In Clojure, with partial function application the order of arguments matters. Its from left to right. This is just like currying. • So, what do we do?
  • 25. Lambda to the rescue • We wrap this in a lambda! (def new-dalal (fn [sal fname]
 (new-person sal fname "Dalal"))) (new-dalal "Mr." "Dhaval") ; Mr. Dhaval Dalal • Doing this by hand every time is tedious! • Fortunately, Clojure has a macro to synthesise this kind of "ad-hoc" partial function application (def new-dalal #(new-person %1 %2 "Dalal")) ; Mr. Dhaval Dalal
 (new-dalal "Mr." "Dhaval") ; Mr. Dhaval Dalal (def new-ada #(new-person %1 "Ada" %2))
 (new-ada "Ms." "Lovelace") ; Ms Ada Lovelace
 (new-ada "Mrs." "???") ; Mrs. Ada ???
  • 26. Currying in Groovy def filterList = { filter, list -> list.findAll(filter) }
 def even = { it % 2 == 0 }
 def evens = filterList.curry(even)
 println evens(0..10) // [0, 2, 4, 6, 8, 10]
 
 def not = { !it }
 def odds = filterList.curry(even >> not) // even andThen not
 println odds(0..10) // [1, 3, 5, 7, 9] • In Groovy, we need to explicitly call the curry method on closure! • It curries from left to right def merge = { x, y, z ->
 println "arg0: x = $x"
 println "arg1: y = $y"
 println "arg2: z = $z"
 "$x$y$z"
 }
 println merge.curry(10)('Hello', new Date()) // 10Hello<Date>
 println merge.curry(10, 'Hello')(new Date()) // 10Hello<Date>
  • 27. Currying in Groovy • And if you need to curry from right-to-left, use rcurry() def merge = { x, y, z ->
 println "arg0: x = $x"
 println "arg1: y = $y"
 println "arg2: z = $z"
 "$x$y$z"
 }
 println merge.rcurry(10)('Hello', new Date()) // Hello<Date>10
 println merge.rcurry(10, 'Hello')(new Date()) // <Date>10Hello • And for currying at a index, use ncurry() println merge.ncurry(1, new Date())(10, 'Hello') //10<Date>Hello
 println merge.ncurry(0, new Date(), 'Hello')(10) //<Date>Hello10
  • 28. Reflections • You curry strictly from left-to-right. • We don’t have to provide all the arguments to the function at one go! This is partially applying the function. • In other words, Currying enables Partial Function Application, a.k.a - Partially Applied Function (PFA). • "ad-hoc PFA" is practically more powerful than currying in some ways. With currying, you have to curry strictly from left to right, with PFA you can do ad-hoc application of args • In a language that deals well with PFA, you won’t really miss currying, because you’ll use PFA where you would have used currying.
  • 29. References • Code Jugalbandi (http://codejugalbandi.org) • Exploring Functional Programming - Ryan Lemmer and Dhaval Dalal • https://github.com/CodeJugalbandi/FunctionalProgramming/ tree/master/melodies/currying • Healthy Code Magazine Code Jugalbandi Article • https://www.slideshare.net/DhavalDalal/3-code- jugalbandicurryingpfahealthycodemagazinemar2015