シェイプレスでは、Nat型は型レベルで自然数をエンコードする方法を表します。これは、たとえば固定サイズのリストに使用されます。型レベルで計算することもできます。 N
要素のリストにK
要素のリストを追加し、コンパイル時にN+K
要素を持つことがわかっているリストを取得します。
この表現は、大きな数字を表現できますか? 1000000
または253、またはこれによりScalaコンパイラがgiveめますか?
自分で試してみます。 Travis BrownまたはMiles Sabinからのより良い回答を喜んで受け入れます。
Natは現在notを使用して大きな数を表すことができます
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]でビット演算を行うときに同じ配列サイズを強制します。
ShapelessのNat
は、Churchエンコーディングを使用して、タイプレベルで自然数をエンコードします。別の方法は、自然をビットのタイプレベルHListとして表すことです。
dense をチェックしてください。これは、このソリューションを形のないスタイルで実装します。
私はしばらく作業していないので、スカラックがgivesめたときのために、あちこちに無形のLazy
を振りかける必要がありますが、コンセプトはしっかりしています:)