Service Symphony

Partial Application, Currying, Composition

In the same way, in the object oriented realm classes and objects are used as the basic building blocks of constructing a larger system of software, in the functional world functions are the basic building blocks. We will look at some of the basic patterns used for using functions as constituents of a composable software architecture.

Partial Application

Let us say, we write a function to find the product of two numbers as below.

scala> def times(x: Int, y: Int) = x * y
times: (x: Int, y: Int)Int
scala> times(2, 10)
res0: Int = 20

Now, let us say we want to reuse the logic above to create functions, where the value of x is constant. You could write a function, that takes a function that takes two arguments and the value of one of its parameters and return a function that takes one argument, reapplying the logic of the initial function, with the value of the first argument fixed. In the functional world this is called partial application of the function.

scala> def times(x: Int, y: Int) = x * y
times: (x: Int, y: Int)Int
scala> def partial(x: Int, f: (Int, Int) => Int) = 
     | (y: Int) => f(x, y)
partial: (x: Int, f: (Int, Int) => Int)Int => Int
scala> val times2 = partial(2, times)
times2: Int => Int = <function1>
scala> times2(10)
res0: Int = 20

If we want to generalise the functional partial, we can use type parameters and write,

scala> def partial[X, Y, Z](x: X, f: (X, Y) => Z): Y => Z = 
     | (y) => f(x, y)
partial: [X, Y, Z](x: X, f: (X, Y) => Z)Y => Z

Since this is a pattern that recur often enough, Scala provides a syntactic sugar to apply the construct as below, where the second parameter can be omitted out as below.

scala> val times2 = times(2, _: Int)
times2: Int => Int = <function1>
scala> times2(10)
res1: Int = 20

The missing parameter is indicated with an underscore. It is a bit strange that we need to specify the type parameter explicitly, but that is an intricacy left to type inference in the language specification.

Currying

Another similar pattern is currying, named after Haskell Curry, where a function that takes n parameters is transformed to n functions that take one parameter each. This pattern can also be used for addressing the functional composition problem addressed in the last section as below,

scala> def curry[X, Y, Z](f: (X, Y) => Z): X => Y => Z =
     | (x) => (y) => f(x, y)
curry: [X, Y, Z](f: (X, Y) => Z)X => (Y => Z)
scala> val curried = curry(times)
curried: Int => (Int => Int) = <function1>
scala> val times2 = curried(2)
times2: Int => Int = <function1>
scala> times2(10)
res2: Int = 20

Again this is a pattern the recur so often, Scala provides a syntactic sugar to write a function that takes a list of n parameters, as a function that takes n set of one parameter each. Based on that, the times function can be written as below,

scala> def times(x: Int)(y: Int) = x * y
times: (x: Int)(y: Int)Int
scala> val times2 = times(2) _
times2: Int => Int = <function1>
scala> times2(10)
res3: Int = 20

Composition

Another common pattern that recurs frequently is the need of chaining two functions, where the output of one function is passed to the input of another as shown below,

scala> def chain[X, Y, Z](a: X => Y, b: Y => Z): X => Z =
     | (x) => b(a(x))
chain: [X, Y, Z](a: X => Y, b: Y => Z)X => Z
scala> def reverse(s: String) = s.reverse
reverse: (s: String)String
scala> def trim(s: String) = s.trim
trim: (s: String)String
scala> val reverseAndTrim = chain(reverse, trim)
reverseAndTrim: String => String = <function1>
scala> reverseAndTrim(" Hello World ")
res5: String = dlroW olleH

The Scala core library provides a function to do the above out of box. The call compose is on the trait Function1, which represents any function that takes one argument.

scala> val reverseAndTrim = reverse _ compose trim _
reverseAndTrim: String => String = <function1>
scala> reverseAndTrim(" Hello World ")
res9: String = dlroW olleH

Share this:

One response to “Partial Application, Currying, Composition”

  1. Lorraine says:

    Good point. I hadn’t thohgut about it quite that way. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

four × 3 =

Some of our
Clients
Service Symphony

Service symphony © 2023

Quick Links
Contact Info

20-22 Wenlock Road
London
N1 7GU
United Kingdom

Support

0800 011 4386