Monads in GridGain: Basics of FP

Monadic operations play a central role in GridGain APIs. So, what is a monad?

One of the best down-to-earth definition of monadic operation is that it is simply a design pattern, a pipeline of function calls defined on an arbitrary set of types. An object that exposes such behavior called monad.

We have monads in Java too. Think of Iterable interface. It defines a monadic operation (i.e. iterator) that is defined for a wide variety of classes (and even some special cases like arrays). Method toString() is another example of a monadic operation. You can ask: what is the difference between a simple interface and monad operations? The answer is: in Java – there’s almost no difference, but in other languages like Scala or Haskel the difference can be that monads do not require an interface and are more powerful concepts because of it.

Back in GridGin 3.0 we have two central concepts in our APIs:

  • GridProjection
  • GridCacheProjection

GridProjection defines a monadic set of operations defined on any arbitrary set of grid nodes. In fact, Grid, GridRichNode and GridRichCloud all implement GridProjection interface and are monadic projections. Grid defines a projection on all nodes in global topology, GridRichNode defines a projection with only one node in it, and GridRichCloud defines a projection for all nodes in the given cloud.

Correspondingly, GridCacheProjection defines a set of monadic operations on any arbitrary set of cache entries (keys, values, or key-value pairs to be specific).

These two concepts give enormous elegancy to our APIs while not making them unnecessary complex. Let me give you couple of examples so that all that would make more sense.

In GridGain 3.0 you can create a dynamic grid projection with a predicate that says that this projection should contain any nodes that, let say, have a specific attribute. Once you have such projection you can now execute closures or tasks on it, send and listen for messages, or do dozens upon dozens of other operations. Now, since this is a dynamic projection any new node joining the grid with a given attribute set will be automatically added to the projection (and vice versa – if a node from this projection leaves the topology it will leave the projection too). This gives you very elegant approach on how to isolate yourself from any changes in cloud topology (example in Java):

GridProjection p = G.grid().projection(new PN() {
	public boolean apply(GridRichNode node) {
		return node.getAttribute(“foobar”) != null;
	}
});

p.execute(…); 

In this example, if projection becomes empty (no nodes in it) – execute(…) operation will rightfully throw an exception.

There are plenty operations to manage projections: you can cross or merge projections, you can examine their size, see if they are empty or dynamic, get a predicate for the projection, and most of the operations on the projection support additional filtering predicates.

Here’s another example with cache projection.

Let’s create cache projection that would filter out any values greater than 10. To do that we create dynamic cache projection with a predicate and since cache projection defines over 95% of all operations available on cache – we can use it directly as named cache instance (example using Scalar – Scala-based DSL for GridGain).

scalar {
    val c = cache[String, Int] ~/ ((e: GridCacheEntry[String, Int]) => e.peek() > 10)
    
    c += "1" -> 1 // That won't be added since value below 10
    c += "1" -> 11 // That will work ok!
}

Now, since predicate can have any logic in it it gives you nice and elegant way to limit or constraint your cache for your specific purposes – yet it doesn’t require any additional APIs on the cache itself. For example, you can create strongly typed projection by specifying the types of keys and values:

scalar {
    val c = cache ~| (classOf[String], classOf[String])

    c += ("skey" -> "sval") // That compiles ok.
    c += ("s" -> 2) // That WON'T compile since 2 is not a String.
}

These examples show just the trivial usage of monadic operations in GridGain. In real applications their usage results in a concise and powerful usage pattern that minimize your code – yet gives it clarity and easier readability.

Enjoy!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: