如何在 Scala 中要求类型安全的常量大小数组? [英] How to require typesafe constant-size array in scala?

查看:32
本文介绍了如何在 Scala 中要求类型安全的常量大小数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要这样的东西:

  def encryptBlock(arr: FixedArray[Size16]) = ???
  val blocks = arr.splitFixed[Size16]
  val encrypted = encryptBlock(FixedArray[Size16]())

所以,为了确保我只收到 128 位数组作为输入.

So, to be sure that I receive only 128-bit array as input.

推荐答案

Shapeless 可以为 seq 做到这一点:

Shapeless can do that for seqs:

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

scala> def func(l: Sized[List[Int], _3]) = l
func: (l: shapeless.Sized[List[Int],shapeless.nat._3])shapeless.Sized[List[Int],shapeless.nat._3]

scala> List(1,2,3,4,5,6).grouped(3).map(_.sized(3).get).map(func)
res26: Iterator[shapeless.Sized[List[Int],shapeless.nat._3]] = non-empty iterator

scala> List(1,2,3,4,5,6).grouped(2).map(_.sized(2).get).map(func)
<console>:25: error: type mismatch;
 found   : shapeless.Sized[List[Int],shapeless.nat._3] => shapeless.Sized[List[Int],shapeless.nat._3]
 required: shapeless.Sized[List[Int],shapeless.Succ[shapeless.Succ[shapeless._0]]] => ?
              List(1,2,3,4,5,6).grouped(2).map(_.sized(2).get).map(func)

传递给.size的参数应该是Literal(Constant(n: Int)),所以你不能传递一些变量或表达式.

Parameter passed to .size should be Literal(Constant(n: Int)), so you can't pass some variable or expression.

也可以将数组转换为某些 IndexedSeq (.toSeq),例如 Vector (.toVector)

It's also possible convert an Array to some IndexedSeq (.toSeq), like Vector (.toVector)

您还可以使用类型析取指定一些可接受的大小集:

You can also specify some set of accepatable sizes using type disjunction:

def func[A <: Nat](l: Sized[List[Int], A])(implicit ev: (_2 with _3) <:< A) = l

func(List(1,2).sized(2).get)
res17: shapeless.Sized[List[Int],shapeless.Succ[shapeless.Succ[shapeless._0]]] = shapeless.Sized@3ac1111f

scala> func(List(1,2,3).sized(3).get)
res18: shapeless.Sized[List[Int],shapeless.Succ[shapeless.Succ[shapeless.Succ[shapeless._0]]]] = shapeless.Sized@17191095

scala> func(List(1,2,3,4).sized(4).get)
<console>:24: error: Cannot prove that shapeless.nat._2 with shapeless.nat._3 <:< nat_1.N.
              func(List(1,2,3,4).sized(4).get)
                  ^

最大 N 限制(来自@DougC 和@Miles Sabin):

Maximum-N restriction (from @DougC and @Miles Sabin):

import ops.nat._
import LT._
scala> def func[N <: Nat](l: Sized[List[Int], N])(implicit ev: N < _3) = l
func: [N <: shapeless.Nat](l: shapeless.Sized[List[Int],N])(implicit ev: shapeless.ops.nat.LT.<[N,shapeless.nat._3])shapeless.Sized[List[Int],N]

scala> func(List(1,2).sized(2).get)
res25: shapeless.Sized[List[Int],shapeless.Succ[shapeless.Succ[shapeless._0]]] = shapeless.Sized@3ac1111f

scala> func(List(1).sized(1).get)
res26: shapeless.Sized[List[Int],shapeless.Succ[shapeless._0]] = shapeless.Sized@73f49b57

scala> func(List(1,2,3).sized(3).get)
<console>:30: error: could not find implicit value for parameter ev: shapeless.ops.nat.LT[nat_1.N,shapeless.nat._3]
              func(List(1,2,3).sized(3).get)
                  ^

这篇关于如何在 Scala 中要求类型安全的常量大小数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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