scala模板函数vs.forSome

scala模板函数vs.forSome,scala,parameterized-types,Scala,Parameterized Types,我正在试验存在主义类型 我在玩一个函数,该函数需要一个序列,其中seq的元素都是相同类型的。我有 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 e

我正在试验存在主义类型

我在玩一个函数,该函数需要一个序列,其中seq的元素都是相同类型的。我有

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>
scala>foo(Seq(新AI,新AS))
:12:错误:类型不匹配;
找到:Seq[A[\u>:String with Int]]
必需:Seq[A[X]]用于某些{type X}
foo(序号(新AI、新AS))
^
scala>bar(顺序(新AI、新AS))
:12:错误:方法栏没有类型参数:(as:Seq[A[X]])布尔值e
xist,以便将其应用于参数(Seq[A[\u>:String with Int]]
---因为---
参数表达式的类型与形式参数类型不兼容;
找到:Seq[A[\u>:String with Int]]
必填项:Seq[A[?X]]
条形图(序号(新AI、新AS))
^
:12:错误:类型不匹配;
找到:Seq[A[\u>:String with Int]]
必填项:Seq[A[X]]
条形图(序号(新AI、新AS))
^
斯卡拉>

不同之处在于,在
foo
中,您不能引用类型
X
,而在
bar
中,您可以:

// fails
def foo(as: Seq[A[X]] forSome { type X }) = Set.empty[X]

// btw the same:
def foo(as: Seq[A[_]]) = Set.empty[???]  // <-- what would you put here?

// OK
def bar[X](as: Seq[A[X]]) = Set.empty[X]
//失败
def foo(as:Seq[A[X]]forSome{type X})=Set.empty[X]
//顺便说一句:

def foo(as:Seq[A[]]]=Set.empty[???]//对于某些
来说,
的范围很重要。您是否尝试过为某些{type X}]
使用Seq[A[X]命令?对于某些来说,考虑存在类型和
的一种可能有用的方法是将其视为一对类型和该类型的一个值。所以一些{type a}
的类型
sometype的值是一对类型
a
以及一些类型可以依赖于
a
的值。如果您想要一个异构列表,您需要该对在
Seq
中的每个元素上都有所不同,并且您的版本在整个
Seq
中都有一个
a
。更进一步,如果您认为存在是与类型成对的,而通用(您的
bar[X]
generic)是与类型相关的函数,您的
foo
bar
类型通过curry/uncurry是同构的。在像Agda这样的依赖类型的语言中,这种关系要清楚得多,但是如果你足够努力地眯着眼睛,你可能也会在Scala中看到它。