Currying in Go and a bit of interfacing

Before you read

I was reading about Currying[1] and wondered how can I use it in Go. It can be useful in some cases. But before going further remember Go is all about simplicity and clarity, from its origin to all aspects of its implementation, so please consider the followings:

  • If you want to use currying extensively maybe you need to see a psychologist or switch to haskell.
  • If you want to use too many empty interfaces in your code, please review your design. In this case making an appointment with a psychologist is optional but at least keep mind that “empty interface{} says nothing”.
  • If you want to argue that what I am doing here is Partial Application[2] or Currying, definitely make an appointment with a psychologist as soon as possible.

Currying

Currying is the process of transforming a function that takes multiple arguments into a series of functions that each take just one argument.

As a simple example if we have a function named f:
f(x,y)={x/y}
Assume x=2, so we will have:
f(2,y)={2/y}
Now imagine h(2) represents f(2,y). h(2) accepts one argument and returns a function of y.
In general you can say h(x) is a new functions that accepts one argument and returns a function of type y.
h(x)=y ⟼ f(x,y)
This h is a curried version of f.

You can read more about the theory in Wikipedia[1].

This concept has its use in Math but the pattern it introduces can be also used in coding.

Usage

Imagine a sample code like the following[3]. It is trying to define a operator functions and apply that operation on a slice of data.

package main
import “fmt”
func mapper(operator func(interface{}) interface{}, m interface{}) (result interface{}) {
switch m.(type) {
case []int:
result := m.([]int)
for i, n := range result {
result[i] = operator(n).(int)
}
return result
}
return result
}
func main() {
square := func(value interface{}) interface{} {
switch value.(type) {
case int:
return value.(int) * value.(int)
}
return nil
}
fmt.Println(mapper(square, []int{1, 2, 3}))
}

We can rewrite the mapper to only get one argument that will be mapping function[4]. Now curriedMapper returns a function. That function gets a slice of data and operates on them in a separate step.

package main
import “fmt”
func curriedMapper(operator func(interface{}) interface{}) func(interface{}) interface{} {
return func(m interface{}) (result interface{}) {
switch m.(type) {
case []int:
result := m.([]int)
for i, n := range result {
result[i] = operator(n).(int)
}
return result
}
return result
}
}
func main() {
square := func(value interface{}) interface{} {
switch value.(type) {
case int:
return value.(int) * value.(int)
}
return nil
}
    squaring := curriedMapper(square)
fmt.Println(squaring([]int{1, 2, 3}))
}

In some case the curried format might be cleaner and more descriptive than the non-curried one. Here we were able to name the result (squaring) and use it later, and re-use it if needed.

Btw, use of interface was completely irrelevant to currying, so if it was confusing, you can look at a simpler code that will assume all actions are on “int” [5].