1. 10

I came across the Wikipedia page on Option types and Nullable types recently … and those pages read like a complete mess:

The “Option types” page seems to be some weird list of implementations/languages that are lawful, but with random languages with wildly different semantics like C#, Perl 6, Java or Julia thrown in.

It also claims that nullable types are practically the same as option types, and the “Nullable types” page itself isn’t much better. “Nullable types” is also some weird mixture of “in many languages null can be assigned to most types” and “what’s Nullable<T>?”

It feels like the whole topic is an incoherent mess – almost like someone wanted to write an article about “banks”, but had to cover both “bank as ” and “bank as ”.

Looking at this purely from a taxonomy perspective and trying to draw from largely established naming patterns – would it makes sense to document different things separately, and with a more precise terminology along the lines of

  • “Option types” as a name for lawful implementations (Haskell, F#, Rust, Idris, Agda, ML, Scala, …)
  • “Optional types” as a name for “pragmatic” (aka incorrect) OOP implementations that support nesting (Java, Julia, C++)
  • “Nullable types” as a name for “pragmatic” (aka incorrect) OOP implementations that do not support nesting (Swift, Perl 6, Kotlin, C#, …)
  • a separate name for “there are languages where String foo = null compiles”?

What do you think about this, and how would your bullet-proof definitions of these names look like?


  2. 3

    Personally, I’d define them entirely by whether they support nesting or not. Option/Optional/Maybe all support nesting, while Null/Nullable/Pointer do not support nesting. Distinguishing between sound and unsound ones just comes down to whether the language has a strong type system.

    1. 3

      I’ve always had an issue with the claim that Option gets rid of null, in the sense that None is null (conceptually and in some cases at runtime). The more precise way to compare unstructured nulls to options is that 1) with options you are usually compelled to explicitly check for null/none/nothing and 2) null does not inhabit other regular types in the language.

      On 2, not all languages enforce this. F#, as an example, has to deal with nulls from the .Net side so point 1 is really the core benefit there. Continuing with .Net as an example though, value types make this null inhabitant impossible as the values are directly represented and it’s not always possible to pick some special null value like zero (int x = 0 in C# certainly doesn’t look null to me). So they add a nullable distinction in .Net and also allow one to explicitly wrap value types to make generics with a nullable constraint work.

      In .Net we might ask, why have null at all? Isn’t it a bad thing? Why would I want types that could be nullable when I hear non-nullable types are the feature we want?

      The real answer is not that null is a bad thing by itself. It’s a value like None. The problem is that it inhabits many or all of your types implicitly and you get no way to say: “I’ve already checked this or I can promise it’s not null”. This is where optional types take the structure of Option but layer it on as if there was an annotation the compiler understands that undoes this mistake of a null inhabitant where it doesn’t belong.

      Now there are also other issues around optional values and good programming practice. I’ve seen codebases where options permeate the codepaths deeply and use combinators to continually build up a value while propagating the null as an exit path the entire distance. This is still bad code even if it’s free of null dereferencing. Making the null explicit makes the issue more obvious but it’s still important to scrub your inputs early and keep strong contracts in place.

        1. 1

          I don’t understand your distinction between “bank as ” and “bank as ”.

          1. 2

            Sorry, it seems like this site stripped out some stuff.

            What I meant to say was: “bank as ” and “bank as ”.