Scala Some redundant covariance - scala

Scala standard library contains Option type.
The Option type itself is covariant type, this is obvious from its declaration sealed abstract class Option[+A].
The questions are:
Why its constructor Some is also covariant
final case class Some[+A](x: A) extends Option[A]?
Is this somehow needed for pattern matching?
Or maybe it's done for better readability?
For me it seems redundant as I don't see any reason to use Some directly anywhere except in pattern matching but currently I can't see how it can depend on covariance.

First, you have to understand that, as #Dima said, Some[T] is not a constructor but a subclass for Option[T].
Once we have established that, the questions with variance are always easier to solve with Dog and Animal:
Is Some[Dog] a Some[Animal]? I think you'll agree that the answer is yes.
Pragmatically, it won't change much, since you'll seldom work with Some[Dog], but rather with Option[Dog], but it may occur (say when you use an unapply of a case class whose signature returns a Some[Tuple]), so why not add the variance while we're at it?

Related

Is there any language construct in scala that can assure all cases of the pattern matching have been handled?

Suppose we have a trait with 3 subcase classes. when we match this trait with two of them and forgot to check the third one, probably, we do not notice it during compile-time and then we get a runtime error especially in the case of using this pattern match in a mutually recursive function.
Is there any Language construct (kind of specific pattern match perhaps) that can assure all subclasses are handled? If so what about more sophisticated pattern matches? (more complex than just matching subclasses of a trait)
Is there any mechanism that can make us assure those pattern matches are total function?
This is not possible in the general case. In a language with dynamic code loading, Class Hierarchy Analysis is equivalent to solving the Halting Problem. Therefore, it is impossible for the compiler to know in the general case how many subclasses the trait has.
You could add or remove subclasses at runtime, also you could add or remove subclasses to the subclasses of the trait, and so on.
It is, however, possible to do this for sealed traits whose subclasses are all also at least sealed or final (thus effectively "turning off" the capability of loading new subclasses at runtime). In that case, Scala will optimize the pattern match to a more efficient representation, and you will get a warning for a non-exhaustive pattern match.
Now all you need to do is to make sure to either read the warning, or tell the compiler to treat warnings as fatal errors (-Xfatal-warnings).
[Technically, the JVM does not know about sealed, so you can actually still load new subclasses using Java Reflection. However, this means you are leaving the realms of Scala, and you are on your own: the Scala compiler cannot protect you from things you do outside of Scala.]
Answered here: What is a sealed trait?
You need to use sealed trait and treat compiler warnings as errors to ensure that match is exhaustive.
sealed trait Base
final class A extends Base
final class B extends Base
val data: Base = new B()
// you get compiler warning here that match might not be exhaustive
// add -Xfatal-warnings to fail compilation on warnings:
// https://docs.scala-lang.org/overviews/compiler-options/index.html
data match {
case _: B => println("B")
}

Why not set covariant as default when define subtype in Scala?

It means define trait Option[T] is same as trait Option[+T].
It's easy to consider val humanOpt: Option[Human] can point to a Option[Student] instance just like val humanOpt: Human can point to a Student instance.
Maybe it seems some strange but why I consider this?
Java variable default as polymorphism which compare with c++ that it should use virtual keyword.I think its a important point to simplify OO in Java.
Scala use high order type in many use case that is more frequently compare to Java, such as Option, Try or define a Cache[T] by ourselves.
Besides, it still comply with Liskov Substitution principle.
I just want to know why not simplify covariant as default behavior?
or define a Cache[T] by ourselves
If your Cache has a put(T) method, it can't be covariant, exactly because of the Liskov substitution principle.
val humanCache: Cache[Human] = new Cache[Student] // legal if cache is covariant
humanCache.put(new Professor) // oops, we put a Professor into a Cache[Student]
So making all types covariant by default simply won't work.
You could use variance inference instead: if type can be covariant make it covariant, if it can be contravariant make if contravariant, if neither make it invariant. But then just adding a method can change the variance and break a lot of code using your type. By making all variance explicit you are forced to notice when you do that.

Scala Nothing datatype

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.

Infer multiple generic types in an abstract class that should be available to the compiler

I am working on an abstract CRUD-DAO for my play2/slick2 project. To have convenient type-safe primary IDs I am using Unicorn as additional abstraction and convenience on top of slicks MappedTo & ColumnBaseType.
Unicorn provides a basic CRUD-DAO class BaseIdRepository which I want to further extend for project specific needs. The signature of the class is
class BaseIdRepository[I <: BaseId, A <: WithId[I], T <: IdTable[I, A]]
(tableName: String, val query: TableQuery[T])
(implicit val mapping: BaseColumnType[I])
extends BaseIdQueries[I, A, T]
This leads to DAO implementations looking something like
class UserDao extends
BaseIdRepository[UserId, User, Users]("USERS", TableQuery[Users])
This seems awfully redundant to me. I was able to supply tableName and query from T, giving me the following signature on my own Abstract DAO
abstract class AbstractIdDao[I <: BaseId, A <: WithId[I], T <: IdTable[I, A]]
extends BaseIdRepository[I,A,T](TableQuery[T].baseTableRow.tableName, TableQuery[T])
Is it possible in Scala to somehow infer the types I and A to make a signature like the following possible? (Users is a class extending IdTable)
class UserDao extends AbstractIdDao[Users]
Is this possible without runtime-reflection? If only by runtime-reflection: How do i use the Manifest in a class definition and how big is the performance impact in a reactive Application?
Also, since I am fairly new to the language and work on my own: Is this good practice in scala at all?
Thank you for help. Feel free to criticize my question and english. Improvements will of course be submitted to Unicorn git-repo
EDIT:
Actually, TableQuery[T].baseTableRow.tableName, TableQuery[T] does not work due to the error class type required but T found, IDEA was superficially fine with it, scalac wasn't.
As for your first question, I've encountered this when working with Slick too. But if you think about it, you'll see you cannot do this at compile time. This is because this type information is necessary specify the relations between your type parameters. If you would not, you would be able to construct classes of BaseIdRepository where the types don't make sense, such as IdTables where the table doesn't represent the projection. Since you need names for each of these relations, you need 3 named type parameters. If you omit the first one, it is possible to construct an IdRepository without a projection containing an Id; if you omit the second one it is possible to have a table without an ID column; and if you omit the third one, it is possible to query tables that do not have this combination of a table and a projection with an ID. You might not have the types defined in your application that would break any of these rules presently, but the compiler doesn't know that. Supplying the proper type information is unavoidable.
As for your second question, it is very unadvisable to employ reflection just because you think the syntax is verbose. If you can make guarantees about typesafety by simply by providing type parameters, I would advise you to do so. It is in very bad taste and style to write Scala in such a way. It would be ironic to employ typesafe ID's with Unicorn and later hack around its type safety with reflection.
Furthermore, a Manifest is not what you want: a manifest doesn't allow you to provide less type information to the compiler, it only allows you to be more flexible to specify where you do so. It allows you to leverage the compiler's knowledge of types at compile time to circumvent some issues that type erasure introduces. The problem you face here has nothing to do with type erasure, so Manifests won't work. Lastly, runtime reflection won't help you much here because Slick's internal functions won't allow you to compile if you don't already supply the type information.
So yeah, what you want is impossible. Scala (and Slick) need complete information at compile time and no trick is going to be effective in circumventing that.

Why are value classes restricted to AnyVal?

As far as I understand value classes in Scala are just there to wrap primitive types like Int or Boolean into another type without introducing additional memory usage. So they are basically used as a lightweight alternative to ordinary classes.
That reminds me of Haskell's newtype notation which is also used to wrap existing types in new ones, thus introducing a new interface to some data without consuming additional space (to see the similarity of both languages consider for instance the restriction to one "constructor" with one field both in Haskell and in Scala).
What I am wondering is why the concept of introducing new types that get inlined by the compiler is not generalized to Haskell's approach of having zero-overhead type wrappers for any kind of type. Why did the Scala guys stick to primitive types (aka AnyVal) here?
Or is there already a way in Scala to also define such wrappers for Scala.AnyRef types?
They're not limited to AnyVal.
implicit class RichOptionPair[A,B](val o: Option[(A,B)]) extends AnyVal {
def ofold[C](f: (A,B) => C) = o map { case (a,b) => f(a,b) }
}
scala> Some("fish",5).ofold(_ * _)
res0: Option[String] = Some(fishfishfishfishfish)
There are various limitations on value classes that make them act like lightweight wrappers, but only being able to wrap primitives is not one of them.
The reasoning is documented as Scala Improvement Process (SIP)-15. As Alexey Romanov pointed out in his comment, the idea was to look for an expression using existing keywords that would allow the compiler to determine this situation.
In order for the compiler to perform the inlining, several constraints apply, such as the wrapping class being "ephemeral" (no field or object members, constructor body etc.). Your suggestion of automatically generating inlining classes has at least two problems:
The compiler would need to go through the whole list of constraints for each class. And because the status as value class is implicit, it may flip by adding members to the class at a later point, breaking binary compatibility
More constraints are added by the compiler, e.g. the value class becomes final prohibiting inheritance. So you would have to add these constraints to any class who want to be inlineable that way, and then you gain nothing but extra verbosity.
One could think of other hypothetical constructs, e.g. val class Meter(underlying: Double) { ... }, but the advantage of extends AnyVal IMO is that no syntactic extensions are needed. Also all primitive types are extending AnyVal, so there is a nice analogy (no reference, no inheritance, effective representation etc.)