Curry On Regardless

14 June 2017

This is the second in a series of posts introducing Functional Programming concepts. Today we're looking at the closely related concepts of Currying and Partial Application.

Some Mystifying Code

Below is a fun piece of code, taken from our React and Redux course.

function logger(store) {
    return function(nextMiddleware) {
        return function(action) {
            const oldValue = store.getState().total;
            nextMiddleware(action);
            const newValue = store.getState().total;
            console.log("Logger: State went from ${oldValue} to ${newValue}");
        }
    }
}

Or if you prefer it in ES6 format:

const logger = store => nextMiddleware => action => {
    const oldValue = store.getState().total;
    nextMiddleware(action);
    const newValue = store.getState().total;
    console.log("Logger: state went from ${oldValue} to ${newValue}");
};

If you remember from the first article in this series Redux is a data store that can be used by JavaScript Web Apps to cache data. Changes in the Redux store are initiated by the arrival of actions, where an action is any JavaScript object with a type property. An additional feature is that Redux allows you to install any number of middleware functions, where a middleware function can intercept incoming actions and perform arbitrary pre or post-processing.

As you can see from this 'hello world' example a middleware function is implemented as a function which takes the Redux store and returns a function that takes the next piece of middleware and returns a function that takes the current action and does something. Obvious really ;-)

To be more explicit:

  1. You provide a function to Redux that takes the current store
  2. This should build and return a function that takes the next middleware
  3. This should build and return a function that takes the action dispatched by the UI
  4. This performs pre-processing, forwards on the action and performs post-processing

Developers not familiar with functional patterns will wonder why they settled on such a bizarre arrangement. Let me try and break down why any architect would go in this direction by taking a more familiar example from OO, the venerable Command Design Pattern.

Command Pattern V1 - Classic OO

The Command Pattern is one of the most popular Gof4 patterns in the software industry, especially in Web Frameworks from Struts onwards. Here's the simplest example I can think of coded in Scala.

Let's say we want to implement a game and need to avoid an 'if ladder' when it comes to writing the event handling code. So instead of a lengthy and unwieldy conditional we have a table of command objects, keyed against the name of the event type.

class Event {}

abstract class Command {
    def execute(e : Event)
}
class StartCommand extends Command {
    override def execute(e : Event)= println("starting to play")
}
class StopCommand extends Command {
    override def execute(e : Event)= {
        println("Bye...")
        System.exit(0)
    }
}
class SaveCommand extends Command {
    override def execute(e : Event)= println("saving current game")
}
class LoadCommand extends Command {
    override def execute(e : Event)= println("loading a new game")
}
object NullCommand extends Command {
    override def execute(e : Event)= println("WOT?")
}

object Program1 {
    def main(args: Array[String]): Unit = {
        val commands = Map("start" -> new StartCommand(),
                           "stop"  -> new StopCommand(),
                           "save"  -> new SaveCommand(),
                           "load"  -> new LoadCommand())

        while(true) {
            val eventName = readLine("What do you want to do?\n")
            commands.getOrElse(eventName,NullCommand).execute(new Event())
        }
    }
}

When an event occurs we simply extract the appropriate command object and invoke its execute method. There is a special NullCommand singleton type that can be used to handle all unknown events. Heres some sample output:

What do you want to do?
start
starting to play
What do you want to do?
load
loading a new game
What do you want to do?
save
saving current game
What do you want to do?
wibble
WOT?
What do you want to do?
stop
Bye...

Command Pattern V2 - FP

It may surprise you to discover that the functional version of this code is much shorter and simpler. We can shed the unnecessary scaffolding of classes and use lambdas for simple actions and named functions for complex ones:

object Program2 {
    type CmdMap = Map[String, Event => Unit]

    def stop(): Unit = {
        println("Bye...")
        System.exit(0)
    }
    def main(args: Array[String]): Unit = {
        val commands : CmdMap = Map(("start", _ => println("starting to play")),
                                    ("stop" , _ => stop()),
                                    ("save" , _ => println("saving current game")),
                                    ("load" , _ => println("loading a new game")))
        while(true) {
            val eventName = readLine("What do you want to do?\n")
            commands.getOrElse(eventName, (_:Event) => println("WOT?")).apply(new Event())
        }
    }
}

In general any pattern that uses a hierarchy of types to model tasks can be simplified via FP concepts.

Command Pattern V3: OO with Properties

Now OO stalwarts will be thinking that this is unfair on the pattern. One of the advantages of Command is that it provides a convenient way to associate state with your event handlers. Let's assume that we need to pass around a Properties object containing, amongst other things, the users name. We have this at startup time but it wont be readily available when events are dispatched, so the logical choice is to pass into the base class constructor like so:

class Event {}

abstract class Command(private val props : Properties) {
    def name() = props.getProperty("name")
    def execute(e : Event)
}
class StartCommand(val p : Properties) extends Command(p) {
    override def execute(e : Event)= println("starting to play " + name() )
}
class StopCommand(val p : Properties) extends Command(p) {
    override def execute(e : Event)= {
        println("Bye " + name())
        System.exit(0)
    }
}
class SaveCommand(val p : Properties) extends Command(p) {
    override def execute(e : Event)= println("saving current game " + name())
}
class LoadCommand(val p : Properties) extends Command(p) {
    override def execute(e : Event)= println("loading a new game " + name())
}
object NullCommand extends Command(new Properties()) {
    override def execute(e : Event)= println("WOT?")
}

object Program3 {
    def main(args: Array[String]): Unit = {
        val props = new Properties()
        props.setProperty("name","Dave")
        val commands = Map("start" -> new StartCommand(props),
                           "stop"  -> new StopCommand(props),
                           "save"  -> new SaveCommand(props),
                           "load"  -> new LoadCommand(props))

        while(true) {
          val eventName = readLine("What do you want to do?\n")
          commands.getOrElse(eventName, NullCommand).execute(new Event())
        }
    }
}

Here's the adjusted output:

What do you want to do?
start
starting to play Dave
What do you want to do?
load
loading a new game Dave
What do you want to do?
save
saving current game Dave
What do you want to do?
wibble
WOT?
What do you want to do?
stop
Bye Dave

Command Pattern V4: FP with Properties

The functional community have a neat solution to this as well, in the form of higher order functions. In the code below you can see that all our event handlers are now named functions that take both a Properties object and an event. However what we are storing in the table is the result of invoking wrapInProps.

This takes a properties object and a function of signature (Properties, Event) => Unit and returns a function of signature (Event) => Unit. In other words we have simplified a function that takes two inputs into a function that takes only one. In other words we have curried the function.

class Event {}

object Program4 {
    type CmdMap = Map[String, Event => Unit]

    def wrapUpProps(p : Properties, f : (Properties, Event) => Unit) = {
        (e : Event) => f(p,e)
    }
    def name(p : Properties) = p.getProperty("name")
    def start(p : Properties, e : Event) = println("starting to play " + name(p))
    def save(p : Properties, e : Event) = println("saving current game " + name(p))
    def load(p : Properties, e : Event) = println("loading a new game " + name(p))
    def stop(p : Properties, e : Event): Unit = {
        println("Bye " + name(p))
        System.exit(0)
    }
    def main(args: Array[String]): Unit = {
        val props = new Properties()
        props.setProperty("name","Dave")
        val commands : CmdMap = Map(("start", wrapUpProps(props,start)),
                                    ("stop" , wrapUpProps(props,stop)),
                                    ("save" , wrapUpProps(props,save)),
                                    ("load" , wrapUpProps(props,load)))
        while(true) {
          val eventName = readLine("What do you want to do?\n")
          commands.getOrElse(eventName, (_:Event) => println("WOT?")).apply(new Event())
        }
    }
}

Command Pattern V5: OO with Properties and Locales

Let's add an extra level of complexity to see this trick performed one more time. Assume that the event handlers also need a Locale object that can be used to internationalise messages. It may not be required in many circumstances but we need to make sure its always available. Let's say the Locale isn't available on setup, so the conventional OO solution would be to supply it later via some form of initialisation method:

class Event {}
class Locale {}

abstract class Command(private val props : Properties) {
    protected var locale : Locale = null

    def init(locale : Locale) = {
        this.locale = locale
    }
    def name() = props.getProperty("name")
    def execute(e : Event)
}
class StartCommand(val p : Properties) extends Command(p) {
    override def execute(e : Event)= println("starting to play " + name() )
}
class StopCommand(val p : Properties) extends Command(p) {
    override def execute(e : Event)= {
        println("Bye " + name())
        System.exit(0)
    }
}
class SaveCommand(val p : Properties) extends Command(p) {
    override def execute(e : Event)= println("saving current game " + name())
}
class LoadCommand(val p : Properties) extends Command(p) {
    override def execute(e : Event)= println("loading a new game " + name())
}
object NullCommand extends Command(new Properties()) {
    override def execute(e : Event)= println("WOT?")
}

object Program5 {
    def main(args: Array[String]): Unit = {
        val locale = new Locale()
        val props = new Properties()
        props.setProperty("name","Dave")

        val commands = Map("start" -> new StartCommand(props),
                           "stop"  -> new StopCommand(props),
                           "save"  -> new SaveCommand(props),
                           "load"  -> new LoadCommand(props))

        commands.values.foreach(_.init(locale))

        while(true) {
            val eventName = readLine("What do you want to do?\n")
            commands.getOrElse(eventName, NullCommand).execute(new Event())
        }
    }
}

As you can see we add an init method to the Command base class and then forEach over the commands to invoke it before we enter the event handling loop.

Command Pattern V6: FP with Properties and Locales

The functional solution would be to modify our existing wrapper function and create a new one.

Firstly we extend wrapUpProps so the function input is of type (Properties, Locale, Event) => Unit and the output of type (Locale,Event) => Unit. Secondly we add a wrapUpLocale function that takes a function input of type (Locale,Event) => Unit and returns one of (Event) => Unit. Although we are applying both at the same time in main there is no reason why we couldn't have an intermediate result.

class Event {}
class Locale {}

object Program6 {
    type CmdMap = Map[String, Event => Unit]

    def wrapUpProps(p : Properties, f : (Properties,Locale,Event) => Unit) = {
        (l : Locale, e : Event) => f(p,l,e)
    }
    def wrapUpLocale(l : Locale, f : (Locale, Event) => Unit) = {
        (e : Event) => f(l,e)
    }
    def name(p : Properties) = p.getProperty("name")
    def start(p : Properties, l : Locale, e : Event) = println("starting to play " + name(p))
    def save(p : Properties, l : Locale, e : Event) = println("saving current game " + name(p))
    def load(p : Properties, l : Locale, e : Event) = println("loading a new game " + name(p))
    def stop(p : Properties, l : Locale, e : Event): Unit = {
        println("Bye " + name(p))
        System.exit(0)
    }
    def main(args: Array[String]): Unit = {
        val locale = new Locale()
        val props = new Properties()
        props.setProperty("name","Dave")
        val commands : CmdMap = Map(("start", wrapUpLocale(locale,wrapUpProps(props,start))),
                                    ("stop" , wrapUpLocale(locale,wrapUpProps(props,stop))),
                                    ("save" , wrapUpLocale(locale,wrapUpProps(props,save))),
                                    ("load" , wrapUpLocale(locale,wrapUpProps(props,load))))
        while(true) {
            val eventName = readLine("What do you want to do?\n")
            commands.getOrElse(eventName, (_:Event) => println("WOT?")).apply(new Event())
        }
    }
}

Command Pattern V7: FP with Partial Invocation

A more formal definition of currying is that we convert a single function that takes 'n' arguments into a chain of functions, each of which takes a single argument. So the solution above solves our problems but doesn't yet meet the definition. To get there with minimal effort we can use Scala's support for Partial Invocation.

In Scala, a function can be given multiple parameter lists and when invoked only the first list need be provided. The others can be omitted, using underscores as placeholders, which directs the compiler to wrap the invocation up in a generated function. Here's a solution implemented using Partial Invocation. Note the multiple parameter lists on the event handlers and the use of the underscore when creating the command map:

class Event {}
class Locale {}

object Program4 {
    type CmdMap = Map[String, Event => Unit]

    def name(p : Properties) = p.getProperty("name")
    def start(p : Properties)(l : Locale)(e : Event) = println("starting to play " + name(p))
    def save(p : Properties)(l : Locale)(e : Event) = println("saving current game " + name(p))
    def load(p : Properties)(l : Locale)(e : Event) = println("loading a new game " + name(p))
    def stop(p : Properties)(l : Locale)(e : Event): Unit = {
        println("Bye " + name(p))
        System.exit(0)
    }
    def main(args: Array[String]): Unit = {
        val locale = new Locale()
        val props = new Properties()
        props.setProperty("name","Dave")
        val commands : CmdMap = Map(("start", start(props)(locale)_),
                                    ("stop" , stop(props)(locale)_),
                                    ("save" , save(props)(locale)_),
                                    ("load" , load(props)(locale)_))
        while(true) {
            val eventName = readLine("What do you want to do?\n")
            commands.getOrElse(eventName, (_:Event) => println("WOT?")).apply(new Event())
        }
    }
}

Command Pattern V8: FP with Partial Invocation and Staged Initialisation

To make our solution equivalent to the OO one let's create an intermediate table of event handlers, where the handlers have been given the Properties object but not the Locale. Note that we require a separate type definition TmpMap to tell the compiler what the type of the functions will be. This means that we cannot accidentally forget to pass in the Locale object, as could be the case with the OO solution and init method. To convert one map to another we can use the standard mapValues function.

class Event {}
class Locale {}

object Program8 {
    type TmpMap = Map[String, Locale => Event => Unit]
    type CmdMap = Map[String, Event => Unit]

    def name(p : Properties) = p.getProperty("name")
    def start(p : Properties)(l : Locale)(e : Event) = println("starting to play " + name(p))
    def save(p : Properties)(l : Locale)(e : Event) = println("saving current game " + name(p))
    def load(p : Properties)(l : Locale)(e : Event) = println("loading a new game " + name(p))
    def stop(p : Properties)(l : Locale)(e : Event): Unit = {
        println("Bye " + name(p))
        System.exit(0)
    }
    def main(args: Array[String]): Unit = {
        val locale = new Locale()
        val props = new Properties()
        props.setProperty("name","Dave")

        val tmp : TmpMap = Map(("start", (start(props)(_))(_)),
                               ("stop" , (stop(props)(_))(_)),
                               ("save" , (save(props)(_))(_)),
                               ("load" , (load(props)(_))(_)))

        val commands : CmdMap = tmp.mapValues(f => f(locale))

        while(true) {
            val eventName = readLine("What do you want to do?\n")
            commands.getOrElse(eventName, (_:Event) => println("WOT?")).apply(new Event())
        }
    }
}

Returning to Our Original Example

To sum up, we have seen how Currying and Partial Invocation are a good choice when:

  1. We want to invoke a function with multiple inputs
  2. These inputs will be available at different times
  3. There is no convenient place to cache the inputs

If we return to the original example of Redux Middleware we can see that all three points apply.

The middleware function:

  1. Will need the action to do anything useful
  2. Will require the next middleware to forward on the action
  3. May potentially need the store itself

However, each of these will be available at different times. The store is always there, the middleware is arranged on setup and actions become available as the store is used. Finally, since Redux is a minimalist framework that integrates with a wide variety of UI's there is no obvious place to cache the inputs until needed.

Conclusions

Hopefully this article has helped clarify some FP terminology, shown how FP concepts compliment OO ones and illustrate how FP concepts and the terminology are being used in emerging frameworks. In the next in the series we will tackle the Jabberwockey of FP concepts - Monads.

If you enjoyed this, why not check out our React and Redux course or one of our Scala courses (Fast-track to Scala or Scala Programming for Java Developers).

Article By
blog author

Garth Gilmour

Head of Learning