Wednesday, 18 February 2009

Currying, some examples and comparisons between C# and Scala

I'm back again! It's been some 3 weeks since my last blog - I've been in New York for 5 days and busy either side sorting out commitments and work and home.

So, in this posting I'd like to continue on the theme of Lamda and functional programming with some simple examples of Currying in both C# .Net (3.0+) and Scala.

I've tried to keep the examples equivalent as closely as possible but Scala has a few different options when it comes to syntax, so the Scala version is a little longer as it delves into these extra possibilities.

What is currying?

In a nutshell currying is "the process of reducing a function that takes multiple arguments into a series of functions that each take one argument"

Named after Haskell Curry - http://en.wikipedia.org/wiki/Haskell_Curry

A good explanation and definition can be found here http://www.haskell.org/haskellwiki/Currying

C# .Net example using C# 3.0+ syntax for Lamdas:


using System;

static class Program
{
static void Main()
{
Func<int, int, int> add = (x, y) => x + y;

var curriedAdd = add.Curry();

var curriedIncrement = add.Curry()(1);
var curriedDecrement = add.Curry()(-1);

Console.WriteLine("curriedAdd(10)(11) = " + curriedAdd(10)(11));
Console.WriteLine("curriedIncrement(41) = " + curriedIncrement(41));
Console.WriteLine("curriedDecrement(41) = " + curriedDecrement(41));
}

// a simple 2 arg curry template function
static Func<TArg1, Func<TArg2, TResult>> Curry<TArg1, TArg2, TResult>(this Func<TArg1, TArg2, TResult> f)
{
return a1 => a2 => f(a1, a2);
}
}

Results:

curriedAdd(10)(11) = 21
curriedIncrement(41) = 42
curriedDecrement(41) = 40

Notes:

  • The use of the var keyword for implicit typing
  • C# does not provide implicit functions/ partial application so a Curry template function for 2 arguments has been provided explicitly.
  • The Curry method is defined as an extension method so it appears as-if defined on add

Extension Method:

static Func<TArg1, Func<TArg2, TResult>> Curry<TArg1, TArg2, TResult>(this Func<TArg1, TArg2, TResult> f)

Take the above definition of a method, the this keyword in the (this Func...) parameter definition makes the function an extension method, so it can be used as if it were declared on the add function - to illustrate the point, without the extension syntax the Curry function could only be invoked in the regular way as follows:

var curriedAdd = Curry(add);

As an extension method, it's valid to use the original add.Curry() or Curry(add) syntax interchangeably.


Scala example:

package test;

object Currying {

def main(args : Array[String]) {

// regular syntax function add
def add(x : int, y : int) = {

x + y
}

// create curried add using 1 and -1 for increment and decrement by invoking partial function (a:int, _:int):int
var curriedIncrement = add(1, _ : int)
var curriedDecrement = add(-1, _ : int)

// test funtions
println("add(10, 11) = " + add(10, 11))
println("curriedIncrement(41) = " + curriedIncrement(41));
println("curriedDecrement(41) = " + curriedDecrement(41));

// curried syntax function add
def add2(x : int)(y : int) = {

x + y
}

// create curried functions using partial functions
var curriedIncrement2 = add2(1)(_ : int)
var curriedDecrement2 = add2(-1)(_ : int)

println("add2(10)(11) = " + add2(10)(11))
println("curriedIncrement2(41) = " + curriedIncrement2(41));
println("curriedDecrement2(41) = " + curriedDecrement2(41));

// special {} syntax
val res1 = add2(10) {
11
}

println("res1 = " + res1)

// more complex example
val x = 1
val y = 2

val z = add2(10) {

add2(20) {

x + y
}
}

println("z = " + z)
}
}


Results:
add(10, 11) = 21
curriedIncrement(41) = 42
curriedDecrement(41) = 40
add2(10)(11) = 21
curriedIncrement2(41) = 42
curriedDecrement2(41) = 40
res1 = 21
z = 33

Notes:
  • Scala supports f(x:int)(y:int) syntax for explicit curried functions
  • Scala supports implicit currying using partial application, using the placeholder _ syntax
  • Scala supports curried parameter in {} syntax for functions that appear to extend the language by taking parameter from the body of the call.



Update:


I realised that the way I'd defined the curried add functions in the Scala example is perhaps not as verbose or explicit as it could have been, and therefore perhaps less easy to understand or compare to the C# example. So here is another code snipped that shows a more verbose currying:


object Currying {

def main(args : Array[String]) {

def add3(x : int) = {

(y : int) => {
x + y
}
}

println("add3(1)(2) = " + add3(1)(2));

val res = add3(5){

3
}

println("res = " + res)
}
}


Results:


add3(1)(2) = 3
res = 8


Resourses:

Good explanation of currying in C#.Net http://diditwith.net/2007/08/15/TheArtOfCurrying.aspx


.

1 comment:

James Iry said...

It's worth mentioning that you can partially apply any method and "+" is a method.

val curriedIncrement = 1 + (_: Int)
val curriedDecrement = -1 + (_: Int)