Scala,强制数组/集合参数的长度

tic*_*fab 1 types scala

假设我有一个类定义为

case class MyClass(myArray: Array[Int])
Run Code Online (Sandbox Code Playgroud)

我只想允许 myArray 参数具有特定长度(例如 3)的实例。

  1. myArray.size == 3我可以在类型/编译级别强制执行吗?
  2. 与其他收藏会有所不同吗?(比如说,一个不可变的列表)

我发现的唯一方法是在运行时通过智能构造函数检查 myArray 的大小并失败 - 例如使用require.

Mar*_*lic 6

我可以在类型/编译级别强制执行 myArray.size == 3 吗?

是的,Scala 可以在类型级别表示数字。例如,使用Sizedfrom shapeless

import shapeless._
import syntax.sized._
import nat._

case class MyClass(myArray: Sized[Array[Int], _3])
MyClass(Sized[Array](1,2,3))         // ok
MyClass(Sized[Array](1,2,3,4))       // compile-time error

Array(1,2,3,4).sized(3).map(MyClass) // None
Run Code Online (Sandbox Code Playgroud)

以下是您在 Scala 3 中使用scala.compiletime.ops工具的方法

import scala.compiletime.ops.int.S

enum MyArray[Size, +A]:
  case Nil extends MyArray[0, Nothing]
  case Cons[N <: Int, B](head: B, tail: MyArray[N, B]) extends MyArray[S[N], B]

import MyArray._

val xs: MyArray[3, Int] = Cons(1, Cons(2, Cons(3, Nil)))
val ys: MyArray[4, Int] = Cons(1, Cons(2, Cons(3, Cons(4, Nil))))

case class MyClass(myArray: MyArray[3, Int])
MyClass(xs) // ok
MyClass(ys) // compile-time error
Run Code Online (Sandbox Code Playgroud)