Trifork Blog

Axon Framework, DDD, Microservices

GOTO Amsterdam: Unfold your Leftfold & Agile Mindset

September 3rd, 2013 by
|

GOTO-Amsterdam-2013 (1)

GOTO Amsterdam already seems a while ago, but I still want to write about two sessions I really enjoyed: the agile mindset (Linda Rising) and a lightning talk about left folds in functional languages (Erik Meijer) unfolded to an object-oriented language.

Unfold your left fold

I never really understood the folding concept in functional programming. At GOTO  Amsterdam I thought, I’ll give my brain a chance again and visited the short talk  from Erik Meijer, where he explained folding in Haskell and later unfolded his fold in  C#.

 Two weeks after the talk, I already forgot how it works, so I decided to work through his  talk in this blog showing some of his samples with Scala and Java.+

So lets get started: imagine you want to compute the sum of all the elements of a list in a functional language, e.g. Scala. The code would look like this:

	def sum(xs: List[Int]): Int = xs match {
		case Nil => 0
		case y :: ys => y + sum(ys)
	}

All of a sudden, we need another function, computing the product of all the elements of a list:

	def product(xs: List[Int]): Int = xs match {
		case Nil => 1
		case y :: ys => y * product(ys)
	}

As we see, we have tons of duplicated code here, although we only changed the operator from + to * and a different initial parameter (0 and 1). We can do better, but therefore we need folding. Enjoy the following line for the summing up a list of three elements:

 List(1, 2, 3).foldLeft(0)((sum, value) => sum + value)

and for the product:

 List(1, 2, 3).foldLeft(1)((product, value) => product * value)

or in short:

 List(1, 2, 3).foldLeft(1)(_ * _)

Easy to read, isn’t it?

But we can also apply it to complex types. Imagine we have a class holding a pair of Int, where we can compute the sum of two Pairs by computing the sums of x and y:

   class Pair(var x : Int, var y : Int) {
        def +(p : Pair) : Pair = new Pair(x + p.x, y + p.y)
   }

We then create a list of Pairs with the initial Pair and compute its sum:

val list = List(new Pair(1,2), new Pair(2,3), new Pair(3,4))

list.foldLeft(new Pair(0,0))((sum, value) => sum + value)

We also need a start element, which is Pair(0,0). The end result is the Pair(6, 9). But this code is bad, we would have code duplication if we additionally need to compute the product. So why not create a generic method compute where we pass a closure function:

class Pair(var x : Int, var y : Int) {
  def compute(p : Pair, f : (Int, Int) => Int) : Pair = {
         new Pair(f(x, p.x), f(y, p.y))
  }
}

Looks like an easy method syntax, does it?!

So now we simply pass the + or the * closure to the compute method. Nice!

val list = List(new Pair(1,2), new Pair(2,3), new Pair(3,4))

list.foldLeft(new Pair(1,1))((result, value) => result.compute(value, (x,y: Int) => x * y))

list.foldLeft(new Pair(0,0))((result, value) => result.compute(value, (x,y: Int) => x + y))

It looks a bit scary, so lets have a look at the signature of the method foldLeft in the Scala library:

def foldLeft[B](z: B)(f: (B, A) => B): B

Damn, that also didn’t help for the understanding. It scares me even more now. Constantly working with Scala doing functional programming is the only solution.

But how would our few lines of Scala code look like in Java? Here we go with… a lot of lines:

public class Pair {

	private final int x;
	private final int y;

	public Pair(int x, int y) {
		this.x = x;
		this.y = y;
	}

	public Pair sum(Pair jp) {
		return new Pair(x + jp.x, y + jp.y);
	}

	public Pair product(Pair jp) {
		return new Pair(x * jp.x, y * jp.y);
	}

	public static Pair computeSum(List list) {
		Pair sum = new Pair(0,0);
		for (Pair jp : list) {
			sum = sum.sum(jp);
		}
		return sum;
	}

	public static Pair computeProduct(List list) {
		Pair product = new Pair(1,1);
		for (Pair jp : list) {
			product = product.product(jp);
		}
		return product;
	}

	public static void main(String[] args) {
		List list = Arrays.asList(new Pair(1,2), new Pair(2,3), new Pair(3,4));
		Pair.computeSum(list);
		Pair.computeProduct(list);
	}
}

Java is better to read, but it is also really verbose.

Erik Meijer presented the foldLeft even a bit more cryptic and I got lost somewhere in the end, but the following unfolding to C# really gave me the motivation to dig deeper into that topic. You save so much code! If you don’t understand these few powerful lines of folding code directly, I recommend to pick a functional language of your choice and learn the folding. It’s yet another powerful tool you can put in our toolbox.

Agile mindset

Linda Rising gave us some insights from social psychology research and how it should influence the way we do our agile projects: the fixed vs. effort (agile) mindset. What’s that? People with a fixed mindset think that intelligence/ability/talent is rather something you are born with and cannot be really changed in your life. People with an effort (agile) mindset think that you can always improve, sometimes even a lot. Based on that initial thought, researchers did the following experiment:

A group of students had to answer a set of simple questions. The group then got categorized into two groups, effort and fixed, by asking them the question if they think if intelligence/ability/talent can be changed or not during a lifetime. It turned out that around 50% of the students thought intelligence/ability/talent is fixed and around 50% thought it’s not. So half of the students had an effort mindset and half of the students had a fixed mindset. After finding out the mindset of each student, the students had to choose between an easy and a difficult test, where 90% of the effort group chose difficult and 80% of the fixed group chose easy. The effort students obviously wanted to get challenged and grow. Furthermore they found out that the effort group enjoyed challenges, gave lots of advice, wanted to know how to get better. On the other side, the fixed group gave only little or no advice, lied about their test scores and were easily discouraged. The researchers found out, that the belief about yourself affects your belief about others: those with a fixed mindset are quick to judge others based on little information and tend to stereotype persons; those with an agile mindset don’t ignore information about others, but they are less positive/negative about it.

Then she put these findings into the context of corporate America and came up with two examples of a fixed mindset company (Enron) and an effort mindset company (Southwestern Airlines). Enron hired ‘best talent’ and ranked and yanked them (ruthlessly grade, sort, fire, promote). Eventually Enron went bankrupt. Southwestern Airlines, on the other side, hired attitude, established a culture of community, trust and spirit; they provide learning opportunities and continually grow people. They are still in business and do well (details of this can be found in the book ‘The talent myth’ from Malcolm Gladwell).

The closing words were then about how these findings fit into agile software development. Within agile software, there’s no standstill, we always have to improve. That means we are *ALL* work-in-progress, no one is fixed, and we should remember that the whole point of a (working) relationship is to encourage each others development. Agile software processes are also never fixed: they continue to change over time as we learn about it, because no method (relationship /code /design /etc) within no project will ever be perfect.

One Response

  1. September 5, 2013 at 10:02 by Rik

    I find the easiest way to wrap your head around left folding, is to rewrite it as good old reduce.

    Your sum example in scala:

    List(1, 2, 3).foldLeft(0)((sum, value) => sum

    becomes this in python:

    reduce(operator.add, [1, 2, 3])

    (Of course, you’d normally use sum() for this, it’s just an example of the syntax)