Subtyping leads to Any: Bug in compiler or issue with my code? - scala

Let me get straight into the problem that I faced while hanging around with type bounds.
Let's consider the following...
I created a function 'foo' like this
def foo[A,B](x:A,y:B):(A,B)=(x,y)
I invoked foo in scala worksheet, like
foo("Mars",2400)
I obtained a result like
res0: (String, Int) = (Mars,2400)
Notice the inferred types of Mars and 2400
Now I wanted to enforce that the function 'foo' accepts Integers or floats or Doubles (any type that is a subtype of AnyVal).
To enforce I wrote a code like
def fooNew[A<:B,B](x:A,y:B):(A,B)=(x,y)
The inferred types from the previous code was (String,Int) and when I invoked fooNew like
fooNew("Saturn",2400)
I was surprised to see that the compiler did let my code pass and did not raise the error instead it did give an output like
res0: (String, Any) = (Saturn,2400)
Now, the desired way of enforcing did not work here. Had I done something like this
def fooNew[A<:B,B<:AnyVal](x:A,y:B):(A,B)=(x,y)
The compiler would have surely raised an error for me and it did!
Error:(2, 2) inferred type arguments [String,Any] do not conform to method fooNew's type parameter bounds [A <: B,B <: AnyVal]
fooNew("Saturn",2400);}
I want to ask, why didn't the compiler the type as Int instead it inferred the type Any and let my code pass the type checks? Do I always need to enforce the second type to be a subtype of AnyVal instead of letting the compiler infer it for me? or is it a bug in the compiler. Seek pardon if you found my question misleading or not upto your expectations.
Currently I am using scala-library 2.11.8
Thankyou

def fooNew[A<:B,B](x:A,y:B):(A,B)=(x,y)
In the above you are declaring type parameter A to be a subtype of type parameter B. When you pass A as String and B as Int, the compiler goes up the class hierarchy to find a suitable type for B such that Int is a B and also String is a subtype of B. The only type in the heirarchy which satisfies these two conditions is the Any type. So, String is a subtype of Any and Int is of type Any

You can think of using your original declaration with inferred types as "find A and B such that x has type A, y has type B, and A is a subtype of B". Since A = String and B = Any satisfy these conditions, the compiler correctly infers them (there are also other solutions, e.g. A = B = Any, but this one is the most specific).
But you can change the declaration to tell the compiler "find A and B such that x has type A and y has type B, and then check that A is a subtype of B". This is done as follows:
def fooNew[A,B](x:A,y:B)(implicit evidence: A <:< B): (A,B)=(x,y)
This works because the compiler will only use the first parameter list to infer A and B. Search for "generalized type constraints" to find more information about <:< and =:=.

Related

Pattern matching with type parameter bounded to final class

Here is an example
def maybeeq[A <: String](x: A):A = x match {
case z:A => x
}
It produced the following error message during compilation
Error:(27, 12) scrutinee is incompatible with pattern type;
found : A
required: String
case z:A => x
I can put any final class into A's bound to reproduce the error.
Why this compiles for non-final classes but fails on the final? Why type erasure not just replace A with String?
Edited:
Note: such bound allows me to pass String-typed value to 'x' parameter. So 'x' can be just a String and don't have to be subtype of string, so I'm not asking compiler to compile method with incorrect signature. In the real-world code I would just put String instead on A parameter, but from the experimental perspective I'm interested why such extra restriction on top of existing restriction (based on final class nature) is needed.
TBH this is a question about compiler design which can only be answered by those who implemented such check
There is a test in compiler test suite that requires such error to be shown. It has something to do with type information being discarded to a point where a concrete type cannot be assigned to variable, but the reasons for that cannot be understood from git blame of that test.
I'll point out, however, that there is still a number of ways to satisfy A <: String without A being known at compile time to be a String. For one, Null and Nothing satisfy that, being at the bottom of Scala type hierarchy. Those two are explicitly disallowed at type matching. The other example is a bit more involved:
val UhOh: { type T <: String } = new { type T = String }
implicitly[UhOh.T <:< String] // satisfies type bound
implicitly[UhOh.T =:= String] // won't compile - compiler cannot prove the type equality
This is similar to some newtyping patterns, e.g. shapeless.tag
Out of all these possibilities, only one that can do anything reasonable is when A =:= String because String is the only type that can be actually checked at runtime. Oh, except when you use generic type in match - that does not work at all (not without ClassTag in scope at least) because such types are eliminated by erasure.
Final class cannot be extended.so for def maybeeq[A <: String](x: A) is not a correct syntax, since String is final, there should not have any subtype extend from String. the compiler smartly point out this issue.

Some[Seq[X]] does not conform to the expected type Option[Seq[X]]

I am new to Scala and I get the compile time error:
Expression of type Some[Seq[String]] does not conform to the expected type Option[Seq[String]]
and this the line in the code
val enabledCipherSuites : Option[scala.collection.immutable.Seq[String]] = Some(Seq("TLS_RSA_WITH_AES_256_CBC_SHA"))
I looked into the Option class source code but can't figure out why Some of a sequence is not Option of Sequence.
Let me know why. Thanks
Edit 1 : I need to explicitly specify that my sequence is immutable as required later in the code
This is because the default Seq you are importing is actually something else, namely scala.collection.Seq. This is defined in scala.Predef, the standard set of imports:
type Seq[+A] = scala.collection.Seq[A]
val Seq = scala.collection.Seq
Now the default variance of Option would work the other way around.
val enabledCipherSuites : Option[Seq[String]] = Some(scala.collection.immutable.Seq("TLS_RSA_WITH_AES_256_CBC_SHA"))
This is because scala.collection.immutable.Seq extends scala.collection.Seq, but obviously not the other way around. The first scenario works because Option is covariant in its type parameter, so you for any B <: A, Option[B] is a subtype of Option[A].
Your case is the opposite, you have immutable.Seq[A] <:< collection.Seq[A], but you're expecting an Option[collection.Seq[A]] to be a subtype of Option[immutable.Seq[A]], which is not true, only the reverse is true.
The Predef import combined with variance is the reason for confusion here.

Why doesn't type inference work here?

This problem arose in a module I'm writing, but I have made a minimal case that exhibits the same behaviour.
class Minimal[T](x : T) {
def doSomething = x
}
object Sugar {
type S[T] = { def doSomething : T }
def apply[T, X <: S[T]] (x: X) = x.doSomething
}
object Error {
val a = new Minimal(4)
Sugar(a) // error: inferred [Nothing, Minimal[Int]] does not fit the bounds of apply
Sugar[Int, Minimal[Int]](a) // works as expected
}
The problem is that the compiler manages to figure out the inner parameter for Minimal (Int), but then sets the other occurrence of T to Nothing, which obviously does not match apply. These are definitely the same T, as removing the first parameter makes the second complain that T is not defined.
Is there some ambiguity that means that the compiler cannot infer the first parameter, or is this a bug? Can I work around this gracefully?
Further information: This code is a simple example of an attempt at syntactic sugar. The original code tries to make |(a)| mean the modulus of a, where a is a vector. Clearly |(a)| is better than writing |[Float,Vector3[Float]](a)|, but unfortunately I can't use unary_| to make this easier.
The actual error:
inferred type arguments [Nothing,Minimal[Int]] do not conform to method apply's type parameter bounds [T,X <: Sugar.S[T]]
This isn't a Scala compiler bug, but it's certainly a limitation of Scala's type inference. The compiler wants to determine the bound on X, S[T], before solving for X, but the bound mentions the so far unconstrained type variable T which it therefore fixes at Nothing and proceeds from there. It doesn't revisit T once X has been fully resolved ... currently type inference always proceeds from left to right in this sort of case.
If your example accurately represents your real situation then there is a simple fix,
def apply[T](x : S[T]) = x.doSomething
Here T will be inferred such that Minimal conforms to S[T] directly rather than via an intermediary bounded type variable.
Update
Joshua's solution also avoids the problem of inferring type T, but in a completely different way.
def apply[T, X <% S[T]](x : X) = x.doSomething
desugars to,
def apply[T, X](x : X)(implicit conv : X => S[T]) = x.doSomething
The type variables T and X can now be solved for independently (because T is no longer mentioned in X's bound). This means that X is inferred as Minimal immediately, and T is solved for as a part of the implicit search for a value of type X => S[T] to satisfy the implicit argument conv. conforms in scala.Predef manufactures values of this form, and in context will guarantee that given an argument of type Minimal, T will be inferred as Int. You could view this as an instance of functional dependencies at work in Scala.
There's some weirdness with bounds on structural types, try using a view bound on S[T] instead.
def apply[T, X <% S[T]] (x: X) = x.doSomething works fine.

Can we infer generic output type?

Consider the following Scala code
def NOTImplementedIn[T<: AnyRef](t:T):String =
throw new Exception(t.getClass.getName+": Input type not implemented")
def NOTImplementedOut[T<: AnyRef](s:String):T =
throw new Exception("Output type not implemented")
In the first case, it is possible to infer the input type T. Is there any way to infer the output type T in the second case? I would like to include the type name in the exception.
The lower type bound of T will always be inferred. If no lower type bound is explicitly given, Nothing is the bound.
This inference is the correct one. As generic parameter type are erased as run time, calls to f[String]("foo"), f[File]("foo") and f[List[Int]]("foo") and f[Nothing]("foo") are the same call f("foo") at run time. The result must be a valid String, File, List[Int], and Nothing. Being Nothing is the only way to satisfy that (which means there will be no result). If there was a stronger lower type bound, it would only need to be of that type.
A consequence of that is that a routine f[T >: LowerBound](parameters): T, where T does not appears in the parameters, is no different from f(parameters): LowerBound, and there is no point in making it generic (when LowerBound is not explicitly stated, the bound is type Nothing)
With the same idea that the call f[T]("foo") is only f("foo") at runtime, it is clear that the name of cannot appear in the exception message. So T has to be someway passed at runtime, and manifests are the normal way to do that, as noted by Dave. Now, T does appear in the parameters, and everything is different. if one calls f[File]("foo"), the compiler will transform that to f("foo")(manifest_of_file) where manifest_of_file allows among other thing to get the name of the type File.
This is still not inference, as File has been explicitly written. The only way type T can be inferred is from the expected type of the call to f in context. If one does val file: File = f("foo"), or passes f("foo") the value of a parameter of type File to some routine, or simply writes f("foo"): File, will File be inferred? No, it won't. Once again, Nothing will be inferred. The reason is that it is a more precise type than File, and as the compiler can pass either a Manifest[File] or a Manifest[Nothing] (and any type in between) it choose the more precise one. This may be surprising for Nothing, but suppose that your lower type bound is String, and the expected type is simply AnyRef, there is no obvious reason to chose AnyRef rather than the better String.
def f[T >: String : Manifest](s: String): T = "type is " + manifest[T].toString
val x: AnyRef = f("foo"): AnyRef
x: Anyref = type is java.lang.String
Same with your example and Nothing as the lower type bound:
def g[T: Manifest](s: String): T = throw new Exception("type is " + manifest[T])
val y: String = g("foo"): String
java.lang.Exception: type is Nothing
at .g(<console>:7)
....
Yes, using a Manifest.
def NOTImplementedOut[T<: AnyRef](s:String)(implicit m: scala.reflect.Manifest[T]):T =
throw new Exception(m.toString + ": Output type not implemented")

Type parameters versus member types in Scala

I'd like to know how do the member types work in Scala, and how should I associate types.
One approach is to make the associated type a type parameter. The advantages of this approach is that I can prescribe the variance of the type, and I can be sure that a subtype doesn't change the type. The disadvantages are, that I cannot infer the type parameter from the type in a function.
The second approach is to make the associated type a member of the second type, which has the problem that I can't prescribe bounds on the subtypes' associated types and therefore, I can't use the type in function parameters (when x : X, X#T might not be in any relation with x.T)
A concrete example would be:
I have a trait for DFAs (could be without the type parameter)
trait DFA[S] { /* S is the type of the symbols in the alphabet */
trait State { def next(x : S); }
/* final type Sigma = S */
}
and I want to create a function for running this DFA over an input sequence, and I want
the function must take anything <% Seq[alphabet-type-of-the-dfa] as input sequence type
the function caller needn't specify the type parameters, all must be inferred
I'd like the function to be called with the concrete DFA type (but if there is a solution where the function would not have a type parameter for the DFA, it's OK)
the alphabet types must be unconstrained (ie. there must be a DFA for Char as well as for a yet unknown user-defined class)
the DFAs with different alphabet types are not subtypes
I tried this:
def runDFA[S, D <: DFA[S], SQ <% Seq[S]](d : D)(seq : SQ) = ....
this works, except the type S is not inferred here, so I have to write the whole type parameter list on each call site.
def runDFA[D <: DFA[S] forSome { type S }, SQ <% Seq[D#Sigma]]( ... same as above
this didn't work (invalid circular reference to type D??? (what is it?))
I also deleted the type parameter, created an abstract type Sigma and tried binding that type in the concrete classes. runDFA would look like
def runDFA[D <: DFA, SQ <% Seq[D#Sigma]]( ... same as above
but this inevitably runs into problems like "type mismatch: expected dfa.Sigma, got D#Sigma"
Any ideas? Pointers?
Edit:
As the answers indicate there is no simple way of doing this, could somebody elaborate more on why is it impossible and what would have to be changed so it worked?
The reasons I want runDFA ro be a free function (not a method) is that I want other similar functions, like automaton minimization, regular language operations, NFA-to-DFA conversions, language factorization etc. and having all of this inside one class is just against almost any principle of OO design.
First off, you don't need the parameterisation SQ <% Seq[S]. Write the method parameter as Seq[S]. If SQ <% Seq[S] then any instance of it is implicitly convertable to Seq[S] (that's what <% means), so when passed as Seq[S] the compiler will automatically insert the conversion.
Additionally, what Jorge said about type parameters on D and making it a method on DFA hold. Because of the way inner classes work in Scala I would strongly advise putting runDFA on DFA. Until the path dependent typing stuff works, dealing with inner classes of some external class can be a bit of a pain.
So now you have
trait DFA[S]{
...
def runDFA(seq : Seq[S]) = ...
}
And runDFA is all of a sudden rather easy to infer type parameters for: It doesn't have any.
Scala's type inference sometimes leaves much to be desired.
Is there any reason why you can't have the method inside your DFA trait?
def run[SQ <% Seq[S]](seq: SQ)
If you don't need the D param later, you can also try defining your method without it:
def runDFA[S, SQ <% Seq[S]](d: DFA[S])(seq: SQ) = ...
Some useful info on how the two differs :
From the the shapeless guide:
Without type parameters you cannot make dependent types , for example
trait Generic[A] {
type Repr
def to(value: A): Repr
def from(value: Repr): A
}
import shapeless.Generic
def getRepr[A](value: A)(implicit gen: Generic[A]) =
gen.to(value)
Here the type returned by to depends on the input type A (because the supplied implicit depends on A):
case class Vec(x: Int, y: Int)
case class Rect(origin: Vec, size: Vec)
getRepr(Vec(1, 2))
// res1: shapeless.::[Int,shapeless.::[Int,shapeless.HNil]] = 1 :: 2 ::
HNil
getRepr(Rect(Vec(0, 0), Vec(5, 5)))
// res2: shapeless.::[Vec,shapeless.::[Vec,shapeless.HNil]] = Vec(0,0)
:: Vec(5,5) :: HNil
without type members this would be impossible :
trait Generic2[A, Repr]
def getRepr2[A, R](value: A)(implicit generic: Generic2[A, R]): R =
???
We would have had to pass the desired value of Repr to getRepr as a
type parameter, effec vely making getRepr useless. The intui ve
take-away from this is that type parameters are useful as “inputs” and
type members are useful as “outputs”.
please see the shapeless guide for details.