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.
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
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 withJava's generic types
, such asIterator<?> or Iterator<? extends Component>
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.