Scala方法类型参数不能接受forSome形式的存在类型

时间:2015-08-11 09:24:38

标签: scala types existential-type

在Scala中,存在类型有以下两种形式:

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

然而,似乎第二种形式不能出现在方法类型参数位置(至少在我写下面的方式)。

  // 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]

我已经尝试了一段时间,但无法找到正确的方法来成功编译第二个。 所以它只是对方法类型参数的一些限制,或者我在这里遗漏了一些东西。

2 个答案:

答案 0 :(得分:5)

令人困惑的是_中的下划线(foo表示存在类型。

让我们看看以下内容实际意味着什么:

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

List这里是一个更高级的kinded类型参数(顺便说一下,引用scala的内置List类型 - aka {{ 1}})。此类型参数本身具有单个类型参数,由下划线(scala.collection.immutable)表示。

现在很明显_在这里不是存在主义,因此List[_]没有业务去那里。

但是,您可以在forSome类型中使用forSome。以下内容相当于x的原始定义:

foo

然后,这可能仍然不是您想要的,因为def foo[List[_]](x: List[T] forSome { type T }) = x 仍然是类型参数而不是 List。你可能想要的是:

scala.collection.immutable

与:

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

答案 1 :(得分:0)

RégisJean-Gilles暗示“这里的列表是一个更高级的类型参数(顺便说一下,并没有引用Scala的内置List类型 - 又名scala.collection.immutable)”,我有一个检查存在类型的定义,最后在我的案例中找出问题,在这里写下来作为RégisJean-Gilles答案的补充。

  

存在类型是一种构造类型的方法,其中类型签名的部分是存在的,其中存在意味着虽然 some real type 符合类型签名的那一部分,但我们并不在意关于具体类型。存在类型被引入到Scala中作为与 Java’s generic types 进行互操作的方法,例如 Iterator<?> or Iterator<? extends Component> (引自 <<Scala In Depth>> )。

真实类型可以是库中的类型(如scala.collection.immutable.List),也可以是我自己定义的类型,如类型别名BB。无论如何,Scala编译器必须保证存在类型的一部分也是已知的

我的问题是

 // 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编译器只知道TT是更高级的类型参数,显然这里没有真正的类型。因此在这种情况下,TT [_]不是存在类型,因此有些形式不能用于类型参数位置。 以下情况有效。

// 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