ShapelessでのNatタイプの制限


151

無形の場合、Nat型は、型レベルで自然数をエンコードする方法を表します。これは、たとえば固定サイズのリストに使用されます。タイプレベルで計算を行うこともできます。たとえば、N要素のリストに要素のリストを追加し、Kコンパイル時にN+K要素があることがわかっているリストを取得します。

この表現は、たとえば10000002または53のような大きな数を表すことができますか、それともScalaコンパイラーが諦めることになりますか?


21
Milesの昨年のNE Scalaのプレゼンテーションはこの質問に対応しており、簡単な答えは、シングルトン型を使用してScalaの型レベルで、または少なくとも2.10で大きな数を表すことができるということですが、価値がないかもしれません。Shapeless 2.0は現在でもChurchエンコーディングを使用しています。これにより、コンパイラが諦める前に1,000程度に到達します。
Travis Brown

3
今日は、もう少しコンテキストを含めて回答を書こうと思います。補足として、より大きな型レベルの数値が必要な場合は、整数のシングルトン型を操作することはそれほど難しくありません。たとえば、こちらのブログ投稿やShapelessのシングルトン機能を参照してください。
Travis Brown

2
大きな型レベルの数値で演算を実行する場合は、ビットのリンクリストとして実装することを検討してください。
Karol S

1
@KarolS私はその戦略の実装を持っています!そして、誰かが興味があれば無形に貢献できればうれしいですが、誰かがstackoverflow.com/questions/31768203/…
beefyhalo

2
stackoverflow.com/questions/31768203/…は解決されたように見えるので、コードを提供して、自分の答えで質問を閉じることができますか?
Andriy Kuba

回答:


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]でビット操作を行うときに同じ配列サイズを強制するために使用できます。


この答えを見ただけで、+ 1、これは良い例です。2つの型レベルの整数が特定の合計を持っていることなどを確認するShapelessなどの型クラスを提供できること注目に値しますops.nat.Sum(それらはマクロによって提供される必要があるだけです)。
Travis Brown

1
以下は、Concatマクロを介して2つの型レベルの文字列を連結できる型クラスの例です。型レベルの整数を合計するための型クラスは、おそらく非常によく似ています。
フランクS.トーマス

5

Shapeless Natは、Churchエンコーディングを使用して、型レベルで自然数をエンコードします。別の方法は、自然をタイプレベルのビットのHListとして表すことです。

このソリューションを形のないスタイルで実装する高密度をチェックしてください。

私はしばらくそれに取り組んでいないのでLazy、スカラックが諦めるときのために、あちこちに無形の散水が必要ですが、コンセプトはしっかりしています :)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.