5

What I mean is this:

scala> class Bounded[T <: String](val t: T)
defined class Bounded

scala> val b: Bounded[_] = new Bounded("some string")
b: Bounded[_] = Bounded@2b0a141e

scala> b.t
res0: Any = some string

Why does res0 have type Any and not String? It sure could know that b.t is at least a String. Writing

val b: Bounded[_ <: String] = new Bounded("some string")

works, but it is redundant with respect to the declaration of the class itself.

Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
Jean-Philippe Pellet
  • 59,296
  • 21
  • 173
  • 234
  • Why not just `val b = new Bounded("some string")`? b is inferred as Bounded[String]. – IttayD Dec 01 '10 at 11:50
  • Isn't it exactly like asking why `val o: Any = "some string"` has type of Any instead of String? – IttayD Dec 01 '10 at 11:51
  • @IttayD Yes, you could omit the type annotation. My actual problem was in a method argument, where you cannot omit it. Besides, I don't agree with your second comment: when I write `b.t`, I'm getting back an object of a type T <: String, so at least a String, as guaranteed by the definition of Bounded. Therefore, I was hoping that res0 would have type String and not any, without using a type annotation like in your example. – Jean-Philippe Pellet Dec 01 '10 at 13:02
  • You should have shown the method problem, then. I imagine it goes like `def m[T](x: T) = new Bounded(x)`? – Daniel C. Sobral Dec 01 '10 at 14:24

2 Answers2

5

First, I have edited the question title. You are not using dependent types, which Scala doesn't have anyway, but existential types. Second, you are not inferring anything, you are explicitly declaring the type.

Now, if you did write Bounded[Any], Scala wouldn't let you. However, one of the uses of existential types is to deal with situations where the type parameter is completely unknown -- such as Java raw types, where.

So my guess is that making an exception in a situation that seems obvious enough will break some other situation where existential type is the only way to deal with something.

Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • Thanks for the edits, Daniel. Now, I don't insist on using "existential types", I'd just like to access b.t passed from a Bounded object with unknown parametrization, and know that it's a String and not Any. Is the only solution to write the type bound as in `val b: Bounded[_ <: String] = new Bounded("some string")`? And have to manually change it everywhere I use Bounded, if some day the type bound in the original declaration of Bounded becomes less restrictive? Argh, raw types... – Jean-Philippe Pellet Dec 01 '10 at 10:46
  • @JPP If you want to know how to avoid writting the boundaries everywhere, please ask it on another question. No one would click on _this_ question to look up for that answer! :-) – Daniel C. Sobral Dec 01 '10 at 14:27
2

There was a lengthy discussion about this topic recently on the mailing list, Type Boundary "Stickyness" on Wildcards.

It wasn't conclusive, other than to agree that existential types, such as Bounded[_] (a shorthand for Bounded[$1] forSome { type $1 }), don't lend themselves to intuition.

@extempore did find one upside to the discussion :)

On the plus side I'm finally reading the spec cover to cover. I had no idea the complete lyrics to "yellow submarine" were in the specification! Yet I have to admit, in context it was hard to see any other way that section could have been written.

retronym
  • 54,768
  • 12
  • 155
  • 168
  • "I had no idea the complete lyrics to "yellow submarine" were in the specification!" ... Where? Which pages? :-P – soc Dec 01 '10 at 14:56