Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

The case for a Couldbe Monad (or why null isn't undefined)

DZone's Guide to

The case for a Couldbe Monad (or why null isn't undefined)

· Java Zone
Free Resource

Learn how to troubleshoot and diagnose some of the most common performance issues in Java today. Brought to you in partnership with AppDynamics.

Several new programming languages are coming with a Maybe type (aka Optional or Option type). In this article, I'd like to advocate for an extended Maybe monad, which I will call a Couldbe monad and that can have three different states: Undefined, None and Some. The distinction between an Undefined and a None value would be very helpful in contexts where null is a perfectly acceptable value and where we want to know if the value of a property is actually null or unknown.

I'm not aware of any discussion about or implementation of such a Couldbe monad (or whatever is the name you want it to have) and I would of course be very interested in such material if somebody can give me a link.

Swift Optionals

I have started using optionals with the brand new Swift language and there is no need to say how meaningful and useful they are, especially when used in chaining expressions.

In Swift, an optional is defined as an enum that can have two possible states:

enum Optional {
    case None
    case Some(T)
}

None represents a null value, while Some carries an actual value of type T. The Swift language makes easy to declare, test and unwrap optionals with the help of the ? and ! operators. For example, the following code snippet declares three optional properties, tests the best friend's name for nullity and accesses its unwrapped value if any:

class Person {
    var name:String?
    var bestFriend:Person?
    var age:Int?
}
var person = Person()
// ...
if person.bestFriend?.name != nil {
    println(person.bestFriend!.name!)
}
// or:
if let name = person.bestFriend?.name as String! {
    println(name)
}

While it is great to have this built-in support of optionals in the Swift language, I'd like to have an extended version of this option type, with the following definition:

enum Optional {
    case Undefined
    case None
    case Some(T)
}

The above code, which tests the best friend's name for nullity, would continue to work exactly the same, but I would also be allowed to check for undefinability. Without going into details about a possible syntax, here is the kinf of code I'd like to write:

if john.bestFriend == nil {
    if john.bestFriend == undefined {
      // we don't know if John has or not a best friend
    }
    else {
      // John doesn't have a best friend
    }
}

But why would we like to have such feature?

Where JavaScript is right

The JavaScript language distinguishes between undefined and null and this distinction is great and meaningful. Given an object, it lets us check if a property exists or if it has a null value:

var person = {
    name: "John",
    bestFriend: null
}

console.log(person.name)        // "John"
console.log(person.bestFriend)  // null
console.log(person.age)         // undefined

While the bestFriend property has a null value (here null is a perfectly defined and legal value which stands for: "John has no best friend"), the age property is simply undefined. It doesn't necessarily mean that John doesn't have an age or that our data model isn't aware of such property: it could mean that the age of John is currently unknown (or undefined) because, for example, our object was retrieved through a remote service that doesn't provide this information.

Now, we all know that JavaScript anonymous objects aren't much more than maps and, accordingly, checking for the existence of an age property in our person is nearly the same as calling the containsKey("age") method on a Java map. There is however a big difference between JavaScript objects and Java maps: if you get a null value from a Java map, there is no way - from the returned value itself - to figure out if it is null because the map actually contains a null value or because the map doesn't have any mapping for the "age" key. On the other hand, you can do the following test with JavaScript:

var age = person.age // person["age"]

if (age == null)
    console.log("age is null or undefined")
if (age === null)
    console.log("age is null")
if (age === undefined)
    console.log("age is undefined")

Which results in the following output:

"age is null or undefined"
"age is undefined"

If we consider a qualified Person object in Java or in Swift, we have no simple way to know if the value of a property is undefined (ie. unknown, uninitialized, not yet set, etc.) or null. This is not a theoretical issue and we can easily find an application of this concept in the context of, for example, JPA entities.

JPA uninitialized associations

Let's consider the following JPA entity:

@Entity
public class Person {

    private String name;

    @ManyToOne(fetch=FetchType.LAZY)
    private Person bestFriend;

    private int age;

    // getters and setters
}

When we fetch one of these persons, the bestFriend property can have three different types of values: no value (no best friend), an uninitialized value (the best friend association wasn't fetched) or an initialized value (the best friend). A Couldbe monad would be helpful here and could even provide a standardized way to represent uninitialized associations (eg. Hibernate uses dynamic proxies while EclipseLink simply uses null in such cases).

Partial serialization

A Couldbe monad would also be extremely useful in the context of partial serialization. I'm currently working on the Spearal serialization protocol (you can read this DZone article on the subject) and one of the key features of this project is to allow the partial serialization of complex data graphs of objects: basically, the idea is that if a client application fetches a list of persons and only displays their names, there are no reasons to serialize all the properties of these persons. It also works the other way: if you send back a person to your server for update and only the name property has changed, there are no reasons to serialize the whole person object.

With Spearal, JPA uninitialized associations are treated as just a particular case of undefined properties. In a JavaScript client, undefined properties are (un)represented by missing keys, while null properties are actually null. It works fine with JavaScript, at least with anonymous objects, but such a possibility is completely missing in Java or Swift: we can't delete a property of a qualified object and, even if there was a way do it, it wouldn't be a clean way of dealing with missing properties.

Generally speaking, we need a way to set a value to an undefined (or unknown, or not yet known) state, and the value itself must be able to carry this information. In Java, we can certainly use dynamic proxies to implement this kind of feature. In Swift, a self-observing object that is KVO-compliant can also hold the extra information needed to know if a property is undefined or not. That's exactly what we are using in Spearal currently but I think that a Couldbe monad would be a much cleaner solution.

Does anybody aware of such extension? Do you have any better idea than this Couldbe monad that could serve the same purpose?

Understand the needs and benefits around implementing the right monitoring solution for a growing containerized market. Brought to you in partnership with AppDynamics.

Topics:

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}