Chapter 63. Optional Is a Lawbreaking Monad but a Good Type
Nicolai Parlog
In most programming languages, empty-or-not-empty types are well-behaved monads. (Yes, I used the M-word—don’t worry, no math.) This means their mechanics fulfill a couple of definitions and follow a number of laws that guarantee safe (de)composition of computations.
Optional
’s methods fulfill these definitions but break the laws. Not without consequences...
Monad Definition
You need three things to define a monad—in Optional
’s terms:
-
The type
Optional<T>
itself -
The method
ofNullable(T)
that wraps a valueT
into anOptional<T>
-
The method
flatMap(Function<T, Optional<U>>
) that applies the given function to the value that is wrapped by theOptional
on which it is called
There’s an alternative definition using map
instead of flatMap
, but it’s too long to fit here.
Monad Laws
Now it gets interesting—a monad has to fulfill three laws to be one of the cool kids. In Optional
’s terms:
-
For a
Function<T, Optional<U>> f
and a valuev
,f.apply(v)
must equalOptional.ofNullable(v).flatMap(f)
. This left identity guarantees it doesn’t matter whether you apply a function directly or letOptional
do it. -
Calling
flatMap(Optional::ofNullable)
returns anOptional
that equals the one you called it on. This right identity guarantees applying no-ops doesn’t change anything. -
For an
Optional<T> o
and two functions ...
Get 97 Things Every Java Programmer Should Know now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.