存在类型和重复参数 [英] Existential types and repeated parameters
问题描述
Scala 中的重复参数的类型是否可以存在存在类型范围?
Is it possible to have an existential type scope over the type of a repeated parameter in Scala?
在这个答案中,我使用以下案例类:
In this answer I use the following case class:
case class Rect2D[A, N <: Nat](rows: Sized[Seq[A], N]*)
它做我想要的,但我不关心 N
(除了需要知道它对所有行都是一样的),并且不想在 中使用它Rect2D
的类型参数列表.
It does what I want, but I don't care about N
(beyond needing to know that it's the same for all the rows), and would prefer not to have it in Rect2D
's type parameter list.
以下版本给了我错误的语义:
The following version gives me the wrong semantics:
case class Rect2D[A](rows: Sized[Seq[A], _ <: Nat]*)
存在在 *
下,所以我不能保证所有的行都具有相同的第二个类型参数——例如,以下编译,但不应该:>
The existential is under the *
, so I don't get the guarantee that all of the rows have the same second type parameter—e.g., the following compiles, but shouldn't:
Rect2D(Sized(1, 2, 3), Sized(1, 2))
以下版本具有我想要的语义:
The following version has the semantics I want:
case class Rect2D[A](rows: Seq[Sized[Seq[A], N]] forSome { type N <: Nat })
这里我使用 forSome
来提升外部 Seq
上的存在.它有效,但我不想在 Rect2D(Seq(Sized(1, 2, 3), Sized(3, 4, 5))) 中编写
Seq
代码>.
Here I'm using forSome
to lift the existential over the outer Seq
. It works, but I'd prefer not to have to write the Seq
in Rect2D(Seq(Sized(1, 2, 3), Sized(3, 4, 5)))
.
我尝试用 *
做类似的事情:
I've tried to do something similar with *
:
case class Rect2D[A](rows: Sized[Seq[A], N] forSome { type N <: Nat }*)
还有:
case class Rect2D[A](rows: Sized[Seq[A], N]* forSome { type N <: Nat })
第一个(毫不奇怪)与 _
版本相同,第二个不能编译.
The first is (not surprisingly) identical to the _
version, and the second doesn't compile.
考虑以下事项:
case class X[A](a: A)
case class Y(xs: X[_]*)
我不希望 Y(X(1), X("1"))
编译.确实如此.我知道我可以写:
I don't want Y(X(1), X("1"))
to compile. It does. I know I can write either:
case class Y(xs: Seq[X[B]] forSome { type B })
或者:
case class Y[B](xs: X[B]*)
但是我想使用重复的参数并且不想在 B
上参数化 Y
.
But I'd like to use repeated parameters and don't want to parametrize Y
on B
.
推荐答案
注意:我之前在这里有一个不同的、无效的解决方案,但我把它删掉了.
Note: I had a different, non-working, solution here before, but I edited it out.
现在第 4 版
sealed trait Rect2D[A] extends Product with Serializable { this: Inner[A] =>
val rows: Seq[Sized[Seq[A], N]] forSome { type N <: Nat }
def copy(rows: Seq[Sized[Seq[A], N]] forSome { type N <: Nat } = this.rows): Rect2D[A]
}
object Rect2D {
private[Rect2D] case class Inner[A](rows: Seq[Sized[Seq[A], N]] forSome { type N <: Nat }) extends Rect2D[A]
def apply[A, N <: Nat](rows: Sized[Seq[A], N]*): Rect2D[A] = Inner[A](rows)
def unapply[A](r2d: Rect2D[A]): Option[Seq[Sized[Seq[A], N]] forSome { type N <: Nat }] = Inner.unapply(r2d.asInstanceOf[Inner[A]])
}
终于有了一个适用于案例类"的版本!我敢肯定,如果我知道如何使用宏,其中的大部分都可以通过宏来消除.
Finally, a version that "works with case classes"! I'm sure most of that could be eliminated by macros, if I only knew how to use them.
这篇关于存在类型和重复参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!