Scala Type Inference Not Working for GADTs in IntelliJ - scala

Following code does not appear as compiling in IntelliJ. It is complaining that the type returned from the eval should be A where I would expect it to infer during usage. The code compiles fine using sbt but does not compile on IntelliJ with both Scala version 2 and 3 (it runs fine but shows error message in code). Is there a special configuration (e.g. sbt params, jvm args etc) that is required for code below to appear as compiled on IntelliJ?
object Solution1 {
trait Expr[A]
case class B(bool: Boolean) extends Expr[Boolean]
case class I(i: Int) extends Expr[Int]
def eval[A](expr: Expr[A]): A = expr match {
case B(b) => b
case I(i) => i
}
}

Generalized algebraic data types (GADTs) are known to be extremely difficult to implement correctly in Scala. AFAIK both the scalac and dotty compilers currently have type soundness holes, particularly using covariant GADTs.
Your eval should return a value of type T, but since i has type Int and b has type Boolean, it seems the compiler is able to see that because I is a subtype of Expr[Int], T must be equal to Int and then T must be equal to Boolean in the same way.
I am surprised this type checks. It's odd because one would expect T to keep it's meaning. It seems Scala 2's GATDs implementation is still faulty.
I'm not surprised Intellij's Scala Plugin flags it red. You can report this, but I'm not sure whether they can do anything about it as it seems Scala is flawed here for the time being. It needs special treatment for them.

Related

Why Scala doesn't deduce trait type parameters?

trait foo[F] {
def test: F
}
class ah extends foo[(Int,Int) => Int] {
def test = (i: Int,j: Int) => i+j
}
So the question is, why Scala known to be so smart about types cannot just deduce type (Int,Int) => Int from the type of test asking me instead to specify it? Or It is still possible? Or maybe this is backed by some thoughts that I don't have in mind.
Your question is basically "why does Scala have only local type inference" or equivalently "why does Scala not have non-local type inference". And the answer is: because the designers don't want to.
There are several reasons for this. One reason is that the most reasonable alternative to local type inference is global type inference, but that's impossible in Scala: Scala has separate compilation and modular type checking, so there simply is no point in time where the compiler has a global view of the entire program. In fact, Scala has dynamic code loading, which means that at compile time the entire code doesn't even need to exist yet! Global type inference is simply impossible in Scala. The best we could do is "whole-compilation-unit type inference", but that is undesirable, too: it would mean that whether or not you need type annotations depends on whether or not you compile your code in multiple units or just one.
Another important reason is that type annotations at module boundaries serve as a double-check, kind of like double-entry book keeping for types. Note that even in languages with global type inference like Haskell, it is strongly recommended to put type annotations on module boundaries and public interfaces.
A third reason is that global type inference can sometimes lead to confusing error messages, when instead of the type checker failing at a type annotation, the type inferencer happily chugs along inferring increasingly non-sensical types, until it finally gives up at a location far away from the actual error (which might just be a simple typo) with a type error that is only tangentially related to the original types at the error site. This can sometimes happen in Haskell, for example. The Scala designers value helpful error messages so much that they are willing to sacrifice language features unless they can figure out how to implement them with good error messages. (Note that even with Scala's very limited type inference, you can get such "helpful" messages as "expected Foo got Product with Serializable".)
However, what Scala's local type inference can do in this example, is to work in the other direction, and infer the parameter types of the anonymous function from the return type of test:
trait foo[F] {
def test: F
}
class ah extends foo[(Int, Int) ⇒ Int] {
def test = (i, j) ⇒ i + j
}
(new ah) test(2, 3) //=> 5
For you particular example, inferring type parameters based on inheritance can be ambiguous:
trait A
trait B extends A
trait Foo[T] {
val x: T
}
trait Bar extends Foo[?] {
val x: B
}
The type that could go in the ? could be either A or B. This is a general example of where Scala will not infer types that could be ambiguous.
Now, you are correct to observe that there is a similarity between
class Foo[T](x: T)
and
trait Foo[T] { x: T }
I have seen work by some into possibly generalizing the similarity (but I can't seem to find it right now). That could, in theory, allow type inference of type parameters based on a member. But I don't know if it will ever get to that point.

Scala Type matching function inside a trait body

I'm new to Scala and working through this book (Function Programming in Scala). One of the exercises involves replicating the Option trait and its functions. However I'm having a problem compiling my solution in the REPL.
sealed trait Nullable[+A] {
def get[B >: A](default: => B) : B = this match {
case Value(v) => v
case Null => default
}
}
case class Value[+A](value: A) extends Nullable[A]
case object Null extends Nullable[Nothing]
REPL error details:
error: constructor cannot be instantiated to expected type;
found : Value[A(in class Value)]
required: Nullable[A(in trait Nullable)]
case Value(v) => v
error: pattern type is incompatible with expected type;
found : Null.type
required: Nullable[A]
case Null => default
Based on those errors I have a nagging feeling that the compiler can't infer that the type of this (being pattern matched on) is a Nullable.
I've tried this block of code on this online Scala utility and it seems to compile and run. The only difference I can see is that the online tool is using Scala version 2.10.3 and I'm running 2.11.7
So I'm not sure if this is environmental or if I need to help the Scala compiler here. I have also tried to compile the answer from the book's authors and I get the same errors.
Any help would be much appreciated.
Posting an answer in case someone else has a similar issue.
Use the REPL :paste command to load the .scala file, instead of the :load command.
Thank you to #noah and #jwvh for the help.

Scala pattern matching on generic type with TypeTag generates a warning while ClassTag not?

I have two very similar methods. The only difference is the use of ClassTag and TypeTag:
def matchClass[A: ClassTag](v: Any) =
v match {
case a: A => "it's A"
case _ => "not A"
}
def matchType[A: TypeTag](v: Any) = ... // same code as matchClass
A compile warning will show for matchType, but not for matchClass:
abstract type pattern A is unchecked since it is eliminated by erasure case a: A
Why is there a warning? why does it show only for TypeTag and not ClassTag?
You don't see a warning for classTag because that check simply works for those:
scala> matchClass[Int]("aaa")
res82: String = not A
scala> matchClass[Int](5)
res83: String = it's A
And doesn't work for typeTag:
scala> matchType[Int](5)
res84: String = it's A
scala> matchType[Int]("aaa")
res85: String = it's A
The reason is that for pattern matching on classTags (when it's seeing an implicit) compiler generates something like:
case a: A if classTag[A].runtimeClass.isInstance(a) => ...
There is no way to get runtimeClass for TypeTags in general (considering both compile&runtime, see the UPDATE for a specific case allowing to extract it in runtime only), so that's why compiler doesn’t transform them. By default, pattern matching can't match on generic (polymorphic) types because of erasure, so you can see that warning by default:
scala> def matchGeneric[A](v: Any) =
| v match {
| case a: A => "it's A"
| case _ => "not A"
| }
<console>:28: warning: abstract type pattern A is unchecked since it is eliminated by erasure
case a: A => "it's A"
^
matchGeneric: [A](v: Any)String
UPDATE: As #Seth Tisue mentioned when a tag comes from run-time universe (only) you can get a runtime class for it (but you gonna have to create a mirror first).
Reference:
As per scaladocs of ClassTag itself:
The compiler tries to turn unchecked type tests in pattern matches into checked ones by wrapping a (_: T) type pattern as ct(_: T), where ct is the ClassTag[T] instance. Type tests necessary before calling other extractors are treated similarly. SomeExtractor(...) is turned into ct(SomeExtractor(...)) if T in SomeExtractor.unapply(x: T) is uncheckable, but we have an instance of ClassTag[T].
TypeTag scaladocs and language spec itself don't mention any such functionality for TypeTags
Speculative explanation
There is no way to know for certain why some features are implemented or not, so any speculation would be opinionated (and out of SO scope, and isn't even related to your question directly, but to answer #Tom's comment). Nevertheless (as of 2.12)...
This is probably because "ClassTags provide access only to the runtime class of a type" and are part of scala-library (even though their package is scala.reflect.), while TypeTags are a part of a separate (and quite wide-broad) reflection API thus are meant to refer to either compile or run time depending on the universe they're in, so writing the additional checks (during synthesis!!) for those would be not just confusing (for users) but also hard for language developers: synthesis itself is in a different (compiler) module and [synthesis] doesn't depend on reflection (only scala-library) as pattern matching synthesis is happening on early "patmat" stage. Also, scala spec (12.3.4.2 Variance) mentions usage of ClassTag's for synthetic adjustments of array instantiations which (very speculatively) could mean that ClassTags are more integrated with the "syntax sugar"-features.

Is ??? a valid symbol or operator in scala

I have seen the symbol
???
used in scala code, i however don't know if it's meant to be pseudo code or actual scala code, but my eclipse IDE for scala doesn't flag it and the eclipse worksheet actually evaluates it.
I haven't been able to find anything via google search.
Any help will be appreciated.
Thanks
Yes, this is a valid identifier.
Since Scala 2.10, there is a ??? method in Predef which simply throws a NotImplementedError.
def ??? : Nothing = throw new NotImplementedError
This is intended to be used for quickly sketching the skeleton of some code, leaving the implementations of methods for later, for example:
class Foo[A](a: A) {
def flatMap[B](f: A => Foo[B]): Foo[B] = ???
}
Because it has a type of Nothing (which is a subtype of every other type), it will type-check in place of any value, allowing you to compile the incomplete code without errors. It's often seen in exercises, where the solution needs to be written in place of ???.
To search for method names that are ASCII or unicode strings:
SO search: https://stackoverflow.com/search?q=[scala]+%22%3F%3F%3F%22
finds this thread Scala and Python's pass
scalex covers scala 2.9.1 and scalaz 6.0 http://scalex.org/?q=%3C%3A%3C

How do you check if a runtime instance conforms to some type using the Scala 2.10 reflection API?

The following snippet returns true as expected:
import scala.reflect.runtime.universe._
typeOf[Seq[Int]] <:< typeOf[Traversable[Int]]
This snippet does not however:
val s = Seq[Int](1,2,3)
val m = runtimeMirror(this.getClass.getClassLoader)
val t = m.reflect(s).symbol.typeSignature
t <:< typeOf[Seq[Int]]
I'm sure that I'm just missing something obvious, but I have been on the REPL for a couple of hours and haven't worked it out. Any suggestions would be much appreciated. Thanks in advance.
1) typeOf[...] preserves the exact Scala type from Java erasure, however, obj.getClass (and consequently m.reflect(obj), which uses getClass under the covers) does not. Consequently, the best runtime reflection can get from reflecting on s without extra compile-time efforts is Seq[_] (which will fail the subtyping test). If you need to remember the exact Scala type of something for runtime, use type tags (just like typeOf does) or macros (just like type tags do).
2) .symbol.typeSignature isn't going to work, because that's ClassInfoType (i.e. a type, which encapsulates a list of parents and members of a class type). Class info types work great for inspecting members (probably also for base classes and maybe for a few more things as well, but I'm not sure off the top of my head), but not so great for everything else. You'd want to go for something like .symbol.asType.toType, which would return a TypeRef (i.e. in our case scala.collection.immutable.:: - note the lack of any type arguments here!). Unfortunately that'd still not work out of the box because of erasure as described in #1.
You don't need reflection to ascertain that a given value conforms to a given statically known type. There are two ways (at least) to do so:
if (someValue.isInstanceOf[SomeType])
...
else
...
or
someValue match {
case st: SomeType => ...
case _ =>
}