Home

Maybe In Ruby

Sometimes it’s fun to do something completely useless.

Recently, I wrote a post about how awesome the Maybe type is in Haskell. In the post, I talked about Functors and Monads and how Maybe can help us understand them.

Shortly thereafter, I was bored on the train one day and decided to implement Maybe and its functor instance in ruby.

In this post I’ll be relying on the fact that obj.(args) is translated to obj.call(args) in newer rubies. I find it makes the example read better.

Maybe

So we need an object that can represent “Just something” or “Nothing”. Ruby already has the concept of nil, so we’ll piggy back on that and just wrap it all in some sugar.

Functions

We can’t map functions to methods because methods need targets, they can’t stand on their own. As an example, take id (which we’ll be using later on). One might be tempted to define it like this:

This won’t work for our purposes since that method (defined on the global object Object) can’t be passed around, partially applied or composed.

It’s more convenient to do it like this:

Now you’ve got an isolated, callable id object which you can pass around.

Partial Application

Functions need to be partially applied. That means you can give a function a few of the arguments it expects and get back another function which you can then pass around and eventually call with the additional arguments given at that later point:

Composition

Two functions, when composed together, return a new function which represents the first being applied to the result of the second being applied to the argument given.

This is all so much easier in Haskell…

Functor

Now that we can define functions, partially apply them and compose them together, we can finally prove the Functor laws for our new Maybe class.

Let’s start by defining fmap, just as it is in Haskell:

Strictly speaking, fmap’s behavior is type-dependant. So a real implementation (for some definition of “real”) would probably make a method on Object which needs to be overridden by any classes that are proper Functors. We won’t worry about that here…

First law, the identity operation must behave the same when it’s fmapped.

So far so good.

Second law, fmapping a composed function is no different than composing the result of each function fmapped separately.

As suspected, our new Ruby-Maybe is a proper Functor.

Monad?

Is our class a Monad?

Proving the laws is left as an exercise to the reader…

01 May 2012, tagged with ruby