Existential types and repeated parameters

Viewed 545

Is it possible to have an existential type scope over the type of a repeated parameter in Scala?

Motivation

In this answer I use the following case class:

case class Rect2D[A, N <: Nat](rows: Sized[Seq[A], N]*)

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.

Stuff I've tried

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 })

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 }*)

And:

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.

Simplified example

Consider the following:

case class X[A](a: A)
case class Y(xs: X[_]*)

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 })

Or:

case class Y[B](xs: X[B]*)

But I'd like to use repeated parameters and don't want to parametrize Y on B.

4 Answers
Related