151

在 shapeless 中,Nat 类型代表了一种在类型级别对自然数进行编码的方法。例如,这用于固定大小的列表。您甚至可以在类型级别上进行计算,例如将N元素列表附加到元素列表K并返回在编译时已知具有N+K元素的列表。

这种表示是否能够表示大数,例如10000002 53,还是会导致 Scala 编译器放弃?

4

2 回答 2

17

我会自己尝试一个。我很乐意接受 Travis Brown 或 Miles Sabin 的更好回答。

Nat 目前不能用于表示大数

在当前的 Nat 实现中,该值对应于嵌套 shapeless.Succ[] 类型的数量:

scala> Nat(3)
res10: shapeless.Succ[shapeless.Succ[shapeless.Succ[shapeless._0]]] = Succ()

因此,要表示数字 1000000,您将拥有一个嵌套 1000000 层深的类型,这肯定会炸毁 scala 编译器。目前的限制似乎是 400 左右,但对于合理的编译时间,最好保持在 50 以下。

但是,有一种方法可以在类型级别对大整数或其他值进行编码,前提是您不想对它们进行计算。据我所知,你唯一能做的就是检查它们是否相等。见下文。

scala> type OneMillion = Witness.`1000000`.T
defined type alias OneMillion

scala> type AlsoOneMillion = Witness.`1000000`.T
defined type alias AlsoOneMillion

scala> type OneMillionAndOne = Witness.`1000001`.T
defined type alias OneMillionAndOne

scala> implicitly[OneMillion =:= AlsoOneMillion]
res0: =:=[OneMillion,AlsoOneMillion] = <function1>

scala> implicitly[OneMillion =:= OneMillionAndOne]
<console>:16: error: Cannot prove that OneMillion =:= OneMillionAndOne.
       implicitly[OneMillion =:= OneMillionAndOne]
                 ^

这可以用于例如在对 Array[Byte] 进行位操作时强制使用相同的数组大小。

于 2015-10-01T13:07:23.053 回答
5

ShapelessNat使用 Church 编码在类型级别对自然数进行编码。另一种方法是将自然表示为位的类型级别 HList。

查看以无形样式实现此解决方案的密集。

Lazy我有一段时间没有研究它了,当 scalac 放弃时,它需要在这里和那里洒一些无形的,但这个概念是可靠的:)

于 2015-11-13T03:21:35.230 回答