I know Scala Nothing is the bottom type. When I see the API it extends from "Any" which is the top in the hierarchy.
Now since Scala does not support multiple inheritance, how can we say that it is the bottom type. In other words it is not inheriting directly all the classes or traits like Seq, List, String, Int and so on. If that is the case how can we say that it is the bottom of all type ?
What I meant is that if we are able to assign List[Nothing] (Nil) to List[String] as List is covariant in scala how it is possible because there is no direct correlation between Nothing and String type. As we know Nothing is a bottom type but I am having little difficulty in seeing the relation between String and Nothing as I stated in the above example.
Thanks & Regards, Mohamed
tl;dr summary: Nothing
is a subtype of every type because the spec says so. It cannot be explained from within the language. Every language (or at least almost every language) has some things at the very core that cannot be explained from within the language, e.g. java.lang.Object
having no superclass even though every class has a superclass, since even if we don't write an extends
clause, the class will implicitly get a superclass. Or the "bootstrap paradox" in Ruby, Object
being an instance of Class
, but Class
being a subclass of Object
, and thus Object
being an indirect instance of itself (and even more directly: Class
being an instance of Class
).
I know Scala Nothing is the bottom type. When I see the API it extends from "Any" which is the top in the hierarchy.
Now since Scala does not support multiple inheritance, how can we say that it is the bottom type.
There are two possible answers to this.
The simple and short answer is: because the spec says so. The spec says Nothing
is a subtype of all types, so Nothing
is the subtype of all types. How? We don't care. The spec says it is so, so that's what it is. Let the compiler designers worry about how to represent this fact within their compiler. Do you care how Any
is able to have to superclass? Do you care how def
is represented internally in the compiler?
The slightly longer answer is: Yes, it's true, Nothing
inherits from Any
and only from Any
. But! Inheritance is not the same thing as subtyping. In Scala, inheritance and subtyping are closely tied together, but they are not the same thing. The fact that Nothing
can only inherit from one class does not mean that it cannot be the subtype of more than one type. A type is not the same thing as a class.
In fact, to be very specific, the spec does not even say that Nothing
is a subtype of all types. It only says that Nothing
conforms to all types.
In other words it is not inheriting directly all the classes or traits like Seq, List, String, Int and so on. If that is the case how can we say that it is the bottom of all type ?
Again, we can say that, because the spec says we can say that.
How can we say that def
defines a method? Because the spec says so. How can we say that a b c
means the same thing as a.b(c)
and a b_: c
means the same thing as { val __some_unforgeable_id__ = a; c.b_:(__some_unforgeable_id__) }
? Because the spec says so. How can we say that ""
is a string and ''
is a character? Because the spec says so.
What I meant is that if we are able to assign List[Nothing] (Nil) to List[String] as List is covariant in scala how it is possible because there is no direct correlation between Nothing and String type.
Yes, there is a direct correlation between the types Nothing
and String
. Nothing
is a subtype of String
because Nothing
is a subtype of all types, including String
.
As we know Nothing is a bottom type but I am having little difficulty in seeing the relation between String and Nothing as I stated in the above example.
The relation between String
and Nothing
is that Nothing
is a subtype of String
. Why? Because the spec says so.
The compiler knows Nothing
is a subtype of String
the same way it knows 1
is an instance of Int
and has a +
method, even though if you look at the source code of the Scala standard library, the Int
class is actually abstract and all its methods have no implementation.
Someone, somewhere wrote some code within the compiler that knows how to handle adding two numbers, even though those numbers are actually represented as JVM primitives and don't even exist inside the Scala object system. The same way, someone, somewhere wrote some code within the compiler that knows that Nothing
is a subtype of all types even though this fact is not represented (and is not even representable) in the source code of Nothing
.
Now since Scala does not support multiple inheritance
Scala does support multiple inheritance, using trait mixin. This is currently not commutative, i.e. the type A with B
is not identical with B with A
(this will happen with Dotty), but still it's a form of multiple inheritance, and indeed one of Scala's strong points, as it solves the diamond problem through its linearisation rules.
By the way, Null
is another bottom type, inherited from Java (which could also be said to have a Nothing
bottom type because you can throw a runtime exception in any possible place).
I think you need to distinguish between class inheritance and type bounds. There is no contradiction in defining Nothing
as a bottom type, although it does not "explicitly" inherit from any type you want, such as List
. It's more like a capability, the capability to throw an exception.
if we are able to assign List[Nothing] (Nil) to List[String] as List is covariant in scala how it is possible because there is no direct correlation between Nothing and String type
Yes, the idea of the bottom type is that Nothing
is also (among many other things) a sub-type of String
. So you can write
def foo: String = throw new Exception("No")
This only works because Nothing
(the type of throwing an exception) is more specific than the declared return type String
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With