在无形状中,Nat类型表示在类型级别编码自然数的方法。这用于例如固定大小的列表。您甚至可以在类型级别进行计算,例如将N
元素列表附加到K
元素列表中,并返回在编译时已知有N+K
个元素的列表。
这种表示能否代表大数字,例如1000000
或2 53 ,或者这会导致Scala编译器放弃吗?
答案 0 :(得分:12)
我会自己尝试一个。我很乐意接受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]上执行位操作时强制执行相同的数组大小。
答案 1 :(得分:2)
无形Nat
使用教会编码在类型级编码自然数。另一种方法是将自然表示为比特的类型级HList。
查看dense以无形样式实现此解决方案。
我暂时没有对它进行过工作,它需要一点点无形的&#39; Lazy
当scalac放弃时,这里和那里,但概念是坚实的:)