2

考虑以下代码片段:

case class Foo[A](a:A)
case class Bar[A](a:A)

def f[B](foo:Foo[Seq[B]], bar:Bar[Seq[B]]) = foo.a ++ bar.a

val s : Seq[T] forSome {type T} = Seq(1, 2, 3)

f(Foo(s), Bar(s))

最后一行类型检查失败,因为Foo(s)has typeFoo[Seq[T]] forSome {type T}Bar(s)has type Bar[Seq[T]] forSome {type T},即每个都有自己的存在量词。

有没有办法解决?实际上,我s在编译时所知道的只是它具有这样的存在类型。我怎样才能强迫Foo(s)Bar(s)落入单个存在量词的范围内?

这有意义吗?我对 Scala 和一般的花哨类型很陌生。

4

2 回答 2

1

我意识到可以通过一些重构来完成这项工作:

case class Foo[A](a:A)
case class Bar[A](a:A)

def f[B](foo:Foo[Seq[B]], bar:Bar[Seq[B]]) = foo.a ++ bar.a
def g[B](s1:Seq[B], s2:Seq[B]) = f(Foo(s1), Bar(s2))

val s : Seq[T] forSome {type T} = Seq(1, 2, 3)

g(s)

本质上,我将调用包装f在另一个函数g中,以保证两个序列具有相同的类型。

于 2015-01-29T03:18:08.787 回答
1

要清楚,

val s : Seq[T] forSome {type T} = Seq(1, 2, 3)

相当于

val s: Seq[_] = Seq(1, 2, 3)

我认为这个问题的答案是否定的。您要么需要使用范围内的类型参数/类型成员,要么需要使用具体类型。

一种方法是使用标记类型:http ://etorreborre.blogspot.com/2011/11/practical-uses-for-unboxed-tagged-types.html

type Tagged[U] = { type Tag = U }
type @@[T, U] = T with Tagged[U]
def tag[A, B](a: A): @@[A, B] = a.asInstanceOf[@@[A, B]]
trait ThisExistsAtCompileTime

case class Foo[A](a:A)
case class Bar[A](a:A)

def f[B](foo:Foo[Seq[B]], bar:Bar[Seq[B]]) = foo.a ++ bar.a

val s : Seq[@@[T, ThisExistsAtCompileTime] forSome {type T}] = Seq(1, 2, 3) map { x => tag[Any, ThisExistsAtCompileTime](x) }

f(Foo(s), Bar(s))
于 2015-01-18T19:02:41.537 回答