Try some monads today

One quality I like in code is easy/quick grokability – from the work grok – to understand thoroughly and intuitively. That is usually enhanced if the code consists of well spaced and familiar lines of code with minimal interruptions – like if/else statements that need their own branches in the method.Every one of these interruptions break the reading of the code and the brain has to make note and focus to see if there’s anything worth noting in the branch inside a method. What can help in structuring code better for grokability are monads.So what’s a monad? Very briefly, it’s a specific way of chaining operations together, as given with some explanation here. A more detailed explanation is given at this link, with lots of code to boot.
The ones I am going to talk about here are in the .Net library, which is available on Nuget and has a wiki here.

OK, so what’s a monad? Well, as you’d have diligently read all the info from the links above :-), you’d know it’s a way of removing redundant code. In a simple code sample:

             if (Orders != null)
                 Orders.ForEach(order => order.Process());

The Orders term is being repeated in the check and the later action. Monads help us write the same code like so:

             Orders.Do(order => order.Process());

And here’s that with exception handling:

             Orders.Do(order => order.TryDo(x => x.Process(), 
                   .Catch(e => _logger.Log(e)));

Not only does the Do method check the Orders object and doesn’t do anything if it’s null, it also iterates over the collection, if there is one, and carries out the required action. So no need for the ForEach call. Of course, there is an overload for a single object.

How about converting:

            string name;
            if(dictionary != null)

               if(dictionary.TryGetValue(id, out name))
                  return View(name);
            return View("");

into the following?

            return View(dictionary.Return(id, "");

This makes it easier to write and read more code in less time – DRY to the extreme, in a way. The library does all the actions in the background and returns the same object to allow chaining of other actions.

With reduction in the lines needed, the code becomes cleaner and, even with spaces between lines, most methods can be groked with a quick glance, so long as the reader understands how monads work. This, along with good OO practises, will keep the classes and methods lean and easy to understand, maintain and extend.

That’s obviously not all. I’ll encourage you to look at the other functionality of this library, it shouldn’t take more than 5-10 mins:

  1. Objects
  2. Collections
  3. Argument Checking
  4. Events

It can be tricky for some to accept this way of doing things, since it is a bit difficult initially to read such code. But like null coalesce operator or dynamic or even generics – after the first few times, the mind adjusts to the new way of thinking and it stops being a hurdle in understanding what’s happening. The way I see it, monads are like the next version features available now.

Yes there is a chance it never becomes integral part of the C# language. But the library is an open source one and anyone can see there is no magic going on under the covers. The features it uses are fairly boiler plate and are unlikely to be left out in the future versions of C#.

When not to use: In some cases of collections having their own collections, it is possible some code will need to treat one level of anonymous collection as object and the next as collection, then again as object. This kind of environment might make it difficult to understand what’s happening and in many cases the library itself cannot make the distinction without explicit implementation. Those sort of places might need refactoring anyway – making sure you tell the objects to do what’s needed instead of asking for state of the object and deciding what to do.


Leave a Reply

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

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

Google photo

You are commenting using your Google 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 )

Connecting to %s