Understand the basics of functional programming paradigm with Ruby examples

Do you remember the first part of this article? Now is the time to go on learning more concepts of Functional Programming.

I’m still reading Functional Programming in Scala by Paul Chiusano and Rúnar Bjarnason, and I still recommend it to anyone who wants to dive into functional programming concepts. It’s getting more and more Scala-ish, so I want to present here some of the patterns in Ruby.

Identity element

An identity element for an operation is an element that leaves the operation’s result unchanged when combined with it.

Let’s define some of these elements for particular operations:

OK. Now, when we are aware of that, how can we use them? Let’s see one of the simplest examples — a sum of elements in an array:

Note that no matter which method we use, there’s still this identity element with a value of 0.

sum = 0

It’s passed either explicitly or implicitly, and now you know what it is, how and why it is used.

Associative operations

This one is simple. The associative laws state that when you add or multiply any three real numbers, the grouping (or association) of the numbers does not affect the result.

Monoids

Monoids come up all the time in everyday programming, even if we are not aware of them. Whenever you’re working with lists, strings or accumulation the result of a loop, you almost for sure use a monoid.

A monoid consists of:

Some type T

An operation that takes two values of type T and combines them into one

An identity element of type T for that operation

It is just a type of constraint so once again — you probably already know it.

Monoids are isolated, immutable and composable way to combine transformations. We can even define our custom class:

Homomorphism

A monoid homomorphism is a function between monoids that preserves the monoid structure.

If two types used by some library are monoids, and there exist functions between them, it’s a good idea to think whether those function preserves monoids structure and check the monoid homomorphism with tests.

Functors

The functional programming languages use the term functor to represent a mapping from types to types, from elements, not necessary of the same type in some kind of a container to another set of elements of the same kind of container. A function that transforms the source element to the target element is provided during implementation. This is a common technique for reusing code.

In Ruby, several objects can be considered function objects, in particular, Method and Proc objects. Ruby also has two kinds of objects that can be thought of as semi-function objects: UnboundMethod and block. UnboundMethods must first be bound to an object (thus becoming a Method) before they can be used as a function object.

Blocks can be called like function objects, but to be used in any other capacity as an object (e.g. passed as an argument) they must first be converted to a Proc. Symbols accessed via the literal unary indicator :, can also be converted to Procs. Using Ruby’s unary & operator is equivalent to calling to_proc on an object.

Let’s see it in action:

How simple is that?

Monads

To start with, I’d like to thank Tom Stuart for an awesome talk about Monads in Ruby. If you haven’t seen it yet, here’s the video:

Theory

As you may think — monads are all about handling nil. They are not language constructs. They’re just types that implement a particular interface, and since Ruby is dynamically typed, any class that implement something like collect in arrays, a join method (like flatten but only flattens one level), and a constructor that can wrap anything, is a monad.

Monads apply a function that returns a wrapped value to a wrapped value. By wrapped value, I mean a value in a context, which is something that affects a particular result for a function application on the same value.

Well, to be honest, monads are far more than that. They are the most complex concept to understand at the very beginning while learning a functional programming.

Implementation

Let’s go through the examples from attached video. A note about naming first: when implementing a Monad we need one abstract type and two concrete classes. There are two schools of naming, one comes from Haskell and one is used in Scala:

Maybe : Nothing | Just

Option : None | Some

Either : Left | Right

You should decide what sounds to you more natural. The point is that either Maybe or Option can hold nothing at all or something with a value. As I’m a big fan of Scala, I’ll stick to the second convention.

Let’s introduce Option first:

We created Option class with all methods from the Enumerable module that basically do the same thing, but the result is wrapped in Option constructor. The constructor just delegates an object instantiation to either None or Some based on whether a value is present and meet particular expectations.

As you can see, None class inherits from Option, and it doesn’t hold any value. All methods are delegated to itself, and underlying enumerable value is represented as an empty array.

Talking about Some we have a little bit more complex logic. Some is used to store a value that responds to all incoming methods.

Here’s how we can use all of them:

I think there’s no need to explain anything here. It’s quite simple to grasp and use in your own code for your convenience.

Ruby monads gems:

Subscribe to get the latest content immediately

https://tinyletter.com/KamilLelonek

Summary

As you can see, there are even more functional programming elements that can be represented in Ruby. As I said before — you don’t have to change your favorite language to leverage these features. Building some parts of your code in a different paradigm may sometimes improve reasoning about it.

Feel free to try them on your own and let me know what parts of FP do you want to read in the next articles.

Resources