2
votes

In Scala, an existential type has the following two forms:

 // placeholder syntax
 List[_]
 // forSome
 List[T forSome {type T}]

However, seems that the second form can not appear in the method type parameter position(at least in the way like I write below).

  // placeholder syntax is Okay
  scala> def foo[List[_]](x: List[_]) = x
  foo: [List[_]](x: List[_])List[_]

  scala> def foo[List[t forSome {type t}]](x: List[_]) = x
  <console>:1: error: ']' expected but 'forSome' found.
  def foo[List[T forSome {type T}]](x: List[_]) = x
                  ^

  // being as upper bound is also Okay
  scala> def foo[A <: List[T forSome { type T }]](x: A) = x
  foo: [A <: List[T forSome { type T }]](x: A)A

  // type alias is a possible way but that is not what I want
  scala> type BB = List[T forSome {type T}]
  defined type alias BB

  scala> def foo[BB](x: List[_]) = x
  foo: [BB](x: List[_])List[Any]

I have tried for a while but been unable to find the right way to get the second compiled successfully. So is it just some restrictions about method type parameter, or am i missing something here.

2

2 Answers

5
votes

The confusion is that the underscore (_) in foo does not denote an existential type.

Let's see what the following actually means:

def foo[List[_]](x: List[_]) = x

List here is a higher kinded type parameter (and by the way does not refer to scala's built-in List type -- aka scala.collection.immutable). This type parameter itself has a single type parameter, denoted by the underscore (_).

Now that it's clear that List[_] is not an existential here, it follows that forSome has no business going there.

However, you can use forSome in the type of x. The following is equivalent to your original definition of foo:

def foo[List[_]](x: List[T] forSome { type T }) = x

Then again, this is probably still not what you'd want, seeing as List is still a type parameter and not scala.collection.immutable. What you'd probably want is:

def foo(x: List[T] forSome { type T }) = x

which is the same as:

def foo(x: List[_]) = x
0
votes

Hinted by Régis Jean-Gilles's "List here is a higher-kinded type parameter (and by the way does not refer to Scala's built-in List type -- aka scala.collection.immutable)", I had a re-check on the definition of existential type and finally figured out the problem in my case, just write it here as complement for Régis Jean-Gilles's answer.

Existential types are a means of constructing types where portions of the type signature are existential, where existential means that although some real type meets that portion of a type signature, we don’t care about the specific type. Existential types were introduced into Scala as a means to interoperate with Java’s generic types, such as Iterator<?> or Iterator<? extends Component>(Quote from <<Scala In Depth>>).

Real type could be type from the library(like the scala.collection.immutable.List), or the self-defined type like type alias BB in my case. Anyway, Scala compiler has to guarantee that part of the existential type is also known.

The problem in my case is that

 // List is type parameter which accepts another type as parameter
 def foo[List[_]](x: List[_]) = x
 // List may be misleading here, just change it to another name
 def foo[TT[_]](x: TT[_]) = x

Scala compiler only knows that TT is higher-kinded type parameter, apparently no real type exists here. So in this case, TT[_] is not a existential type therefore forSome form can not be used in the type parameter position. And the following cases are valid.

// we define a higher-kined type HKT, so HKT is a real type 
// when Scala compiler checks the method parameter part
// HKT can be defined as existential type
def foo[HKT[_]](x: HKT[T forSome { type T }]) = x
def foo[HKT[_]](x: HKT[T] forSome { type T }) = x