3

From this question: Sample of `forSome { val `?

I learnt that, if I use this format of existential type:

type SomeList = List[v.T] forSome { val v : { type T }; }

There must be a type named T in the code.

But this code:

List[T] forSome { type T }

Although there is a { type T } as well, but it doesn't require a type named T exist, instead, it can match any type.

I can't understand why there is such difference, and can I expect the { type T } parts of two kinds have the exact same meaning?

Community
  • 1
  • 1
Freewind
  • 193,756
  • 157
  • 432
  • 708

1 Answers1

0

OK, I'll have a try (though existential types are quite new to me too...)

Your first example uses a path-dependent type v.T, and means "given a value v containing a type called T, construct the type of List whose elements have type (v.T)".

Your second example

List[T] forSome { type T }

means "a list of type T where T could be any type", and is equivalent to:

List[_]

(The compiler actually gives the type as List[_] in Eclipse. David R. MacIver's article discusses this in more detail.)

so probably isn't very useful unless you add additional bounds to the type T

In the first example we are referring to a very specific named (path-dependent) type; In the answer to your linked question, T must exist and be bound to a concrete type, because we use it to access a value of that type:

object X { 
  type T = String
  val x: T = "hello" 
}

in the second example, we are referring to any type at all.

I think the different meaning of the same syntax is due to the different context (path-dependent type or plain type).

See also :

DNA
  • 42,007
  • 12
  • 107
  • 146