scala - Scala中的现有类型

标签 scala types enums existential-type

关于存在性类型的困惑不大。

这对我有用:

def valueOf(c: Class[_], name: String) {
  type C = Class[T] forSome {type T <: Enum[T]}
  Enum.valueOf(c.asInstanceOf[C], name)
} 

但这不是:
def valueOf(c: Class[_], name: String) {
  type T = T forSome {type T <: Enum[T]}
  Enum.valueOf(c.asInstanceOf[Class[T]], name)
}

在我看来,这两种表达方式都等同于:
Enum.valueOf(z.asInstanceOf[Class[T] forSome {type T <: Enum[T]}], name)

但是Scala说这只是我的想法:
inferred type arguments [T] do not conform to method valueOf's type parameter bounds [T <: Enum[T]]
         Enum.valueOf(c.asInstanceOf[Class[T]], name)
              ^

最佳答案

请考虑以下两个表达式之间的区别:

Enum.valueOf(x.asInstanceOf[Class[X] forSome { type X <: Enum[X] }], name)

和:
Enum.valueOf(x.asInstanceOf[Class[X forSome { type X <: Enum[X] }]], name)

现在考虑在每种情况下如何推断T的类型参数valueOf。在第一种情况下,我们拥有一个X,我们知道它是Enum[X]的子类型,并且我们都已准备就绪。另一方面,在第二种情况下,T必须是X forSome { type X <: Enum[X] },并且至关重要的是,该类型不是Enum[X forSome { type X <: Enum[X] }]的子类型,因此我们没有满足T的约束。

问题在于您的第二个示例与后者等效。

作为注脚,如果Enum的类型参数是协变的,则此方法会很好地工作。请使用以下简化示例:
trait Foo[A]
trait Bar[A]

def foo[A <: Bar[A]](f: Foo[A]) = f

def x: Foo[X] forSome { type X <: Bar[X] } = ???
def y: Foo[Y forSome { type Y <: Bar[Y] }] = ???

现在foo(x)将会编译,但是foo(y)不会编译,就像在您的代码中一样。但是,请稍微更改Bar:
trait Foo[A]
trait Bar[+A]

def foo[A <: Bar[A]](f: Foo[A]) = f

def x: Foo[X] forSome { type X <: Bar[X] } = ???
def y: Foo[Y forSome { type Y <: Bar[Y] }] = ???

现在他们都将进行编译。我猜想这与我们对两个示例具有相同的直觉有很强的直觉有关。

作为另一个脚注(响应gzmocomment below),请考虑以下内容:
scala> trait Foo[A <: Foo[A]]
defined trait Foo

scala> class MyFoo extends Foo[MyFoo]
defined class MyFoo

scala> val myFoo = new MyFoo
myFoo: MyFoo = MyFoo@3ee536d

scala> myFoo: (X forSome { type X <: Foo[X] })
res0: X forSome { type X <: Foo[X] } = MyFoo@3ee536d

scala> myFoo: Foo[MyFoo]
res1: Foo[MyFoo] = MyFoo@3ee536d

让我们假设X forSome { type X <: Foo[X] }Foo[X forSome { type X <: Foo[X] }]的子类型(暂时忽略后者甚至不是有效类型的事实)。然后,我们将能够编写以下代码:
myFoo: Foo[X forSome { type X <: Foo[X] }]

但是Foo是不变的,因此,如果我们有一些东西既是Foo[A]又是Foo[B]的实例,那么A =:= B一定是这种情况。但是MyFoo =:= (X forSome { type X <: Foo[X] })绝对不是这种情况。不确定所有这些内容是否会引起混淆,但这就是我说服自己编译器知道它在做什么的方式。

关于scala - Scala中的现有类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18396572/

相关文章:

java - Spark的scala代码如何暴露为Java API?

scala - 使用 Spark Streaming 读取 fileStream

c++ - 什么是声明和声明符?标准如何解释它们的类型?

java - 为什么枚举单例是序列化安全的?

java - scala akka 微内核中线程 "main"java.lang.InstantiationException 中的异常

scala - Scala 中的哪些功能/特性仅作为对底层平台的让步而存在,如果针对其他目标应该删除?

php - 在 PHP 中指定类的对象类型的方法

sql-server - 在 Sql Server 中存储 UInt32 的最佳方法

c++ - 常量 X 不是类型名称,这里 x 是 KING

c# - C# 中的枚举 bool 值