What is “Nothing”?
Nothing is a subtype of all types, also called the bottom type.
https://docs.scala-lang.org/tour/unified-types.html
As the Scala official doc says, Nothing
is a subtype of all types. That means, Nothing
is a subtype of Int
and also is a subtype of String
and List[User]
.
When I happened to see the definition at the first time, I was confused, and I read that definition out again and again, but I couldn’t figure out what does it mean. A subtype of Int
, String
, and List[User]
. Is there such a magical value?
Of course, Scala doc answers to this quite natural question.
There is no value that has type Nothing
https://docs.scala-lang.org/tour/unified-types.html
“There is no value that has type Nothing”. Again, I read it out again and again, but it definitely says there is no value like that. It’s weird. If there’s no such value, what is Nothing
type for?
… In fact, Nothing
is definitely an important part of the Scala’s type system.
Type for expression which doesn’t return a value
Assume you have a method that returns Int
or throws an exception.
def oneOrThrow(num: Int): Int =
if (num == 1) num
else throw new Exception(s"$num is not 1")
The if
expression should be an Int
. In the positive case, num
is apparently Int
, but how about else
case? If you add type annotation to the both cases, that should look like this to return Int
:
def oneOrThrow(num: Int): Int =
if (num == 1) (num: Int)
else (throw new Exception(s"$num is not 1")): Int
Actually we can compile this without an error! throw new Exception(s"$num is not 1")
's type can be Int
. In the same way, it should be legitimate to use throw
where any possible type is required.
// These snipets can be compiled without an error.
val int: Int = throw new Exception("fake Int")
val string: String = throw new Exception("fake String")
val maybeUser: Option[User] = throw new Exception("fake User")
def equalsOrFail[A](l: A, r: A): A =
if (l == r) l
else throw new Exception(s"$l is not $r")
Here, Scala compiler treats throw
expressions as Nothing
type. Do you remember? Nothing
is a subtype of all types so it can be an Int
, String
, and A
. throw
doesn’t return an concrete value, but it should be any type. Here, Nothing
seems to be a perfect choice. Thanks to it, Scala type checker can treat throw
like any other expression.
Stub
Another usage of Nothing
is ???
. ???
is useful when developing an outline of features without considering their implementation detail.
// TODO: Implement them later.
def resolveAuthor(authorId: AuthorId): Future[User] = ???
def storeAuthor(author: Author): Future[Unit] = ???def updateAuthorName(authorId: AuthorId, name: AuthorName): Future[Unit] =
for {
author <- resolveAuthor(authorId)
_ <- storeAuthor(author.updateName(name))
} yield ()
Quite useful. Anyway, an interesting and beautiful fact about ???
is that it’s not a special syntax like throw
, but just a method defined at Predef
as Nothing
type.
def ??? : Nothing = throw new NotImplementedError
Thanks to its flexibility of Nothing
, we can use ???
as a stub of any required type.
Empty object for higher kinded types
The last example I introduce is for empty object like Nil
or None
. Higher kinded type like Option
andList
MAY contain A
values in it. At the same time, they MAY NOT contain a value, and such empty values are declared as Nil
or None
in Scala.
You might have used None
as type Some[Int]
or you might have used Nil
as List[User]
. Again, Nothing
helps this flexibility.
sealed abstract class Option[+A]final case class Some[+A](value: A) extends Option[A] { ... }case object None extends Option[Nothing] { ... }
Here, Nothing
is used as type parameter +A
of Option[+A]
. This +
variance is important to let Option[B]
replace Option[A]
when B
is a subtype of A
. As I mentioned many times in this post, Nothing
is a subtype of all types. Therefore Option[Nothing]
is a subtype of Option[Int]
and Option[User]
and all possibleOption[A]
types. There is no value of Nothing
, but it’s not a problem because both Nil
and None
are empty.
Conclusion
At first glance, Nothing
is weird and useless. However, its replaceability is quite powerful in Scala’s type system. I introduced some usages which I think are beautiful. You might not aware of Nothing
in daily programming, but definitely it makes Scala more elegant.