【发布时间】:2013-04-19 22:39:44
【问题描述】:
我正在尝试存在类型。
我正在使用一个函数,该函数需要一个序列,其中该序列的元素都是相同的类型。我有..
def bar[X](as: Seq[A[X]]) = true
在哪里...
// parametised type to use in the question
trait A[T]
然后我遇到了“forSome”语法,发现我可以用它实现相同的约束。
出于比较目的,我写了以下内容...
// useful types
trait A[T]
class AI extends A[Int]
class AS extends A[String]
// define two functions that both have the same constraint.
// ie the arg must be a Sequence with all elements of the same parameterised type
def foo(as: Seq[A[X]] forSome { type X }) = true
def bar[X](as: Seq[A[X]]) = true
// these compile because all the elements are the same type (AI)
foo(Seq(new AI, new AI))
bar(Seq(new AI, new AI))
// both these fail compilation as expected because
// the X param of X[A] is different (AS vs AI)
foo(Seq(new AI, new AS))
bar(Seq(new AI, new AS))
我想了解的是 - 我错过了什么吗? 一个签名比另一个签名有什么好处。
一个明显的区别是编译错误是不同的。
scala> foo(Seq(new AI, new AS))
<console>:12: error: type mismatch;
found : Seq[A[_ >: String with Int]]
required: Seq[A[X]] forSome { type X }
foo(Seq(new AI, new AS))
^
scala> bar(Seq(new AI, new AS))
<console>:12: error: no type parameters for method bar: (as: Seq[A[X]])Boolean e
xist so that it can be applied to arguments (Seq[A[_ >: String with Int]])
--- because ---
argument expression's type is not compatible with formal parameter type;
found : Seq[A[_ >: String with Int]]
required: Seq[A[?X]]
bar(Seq(new AI, new AS))
^
<console>:12: error: type mismatch;
found : Seq[A[_ >: String with Int]]
required: Seq[A[X]]
bar(Seq(new AI, new AS))
^
scala>
【问题讨论】:
-
forSome的范围很重要。你试过Seq[A[X] forSome { type X }]吗?考虑存在类型和forSome的一种可能有用的方法是将其视为一对类型和该类型的值。所以sometype forSome { type A }类型的值是A类型的一对以及一些类型可以依赖于A的值。如果您想要一个异构列表,您需要该对在Seq中的每个元素上有所不同,并且您的版本对于整个Seq有一个A。 -
更进一步,如果您将存在性视为与类型的配对,而将普遍性(您的
bar[X]泛型)视为具有类型的函数,您的foo和bar类型是同构的, 通过currying/uncurrying。这种关系在像 Agda 这样具有依赖类型的语言中要清晰得多,但如果你足够仔细地眯着眼睛,你也可能在 Scala 中看到它。