存在类型和重复参数 [英] Existential types and repeated parameters

查看:42
本文介绍了存在类型和重复参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆