Обмеження типу Nat в Shapeless


151

Безформний тип Nat представляє спосіб кодування натуральних чисел на рівні типу. Це використовується, наприклад, для списків фіксованого розміру. Ви навіть можете робити розрахунки на рівні типу, наприклад, додавати список Nелементів до списку Kелементів і повертати список, який, як відомо, під час компіляції матиN+K елементи.

Чи здатне це представництво представляти велику кількість, наприклад, 1000000або 2 53 , чи це спричинить скасування компілятора Scala?


21
Презентація NE Scala Майлза минулого року стосується цього питання, і коротка відповідь полягає в тому, що можна було б представити великі числа на рівні типу в Scala - або, принаймні, в 2.10 - з використанням однотипних типів , але це, можливо, не варто . В даний час Shapeless 2.0 все ще використовує кодування Церкви, яке отримає вас до 1000 або більше, перш ніж компілятор відмовиться.
Травіс Браун

3
Спробую написати відповідь з трохи більше контексту пізніше сьогодні. Як бічне зауваження, працювати з цілими типами одиночних типів не надто складно, якщо вам потрібні більші типи рівнів типу - див., Наприклад, мій пост в блозі тут або функцію одиночної форми в Shapeless .
Тревіс Браун

2
Якщо ви хочете робити арифметичні великі числа на рівні типу, ви можете розглянути їх реалізацію як пов'язаний список бітів.
Karol S

1
@KarolS У мене є реалізація цієї стратегії! І я буду радий внести свій вклад його в безформну , якщо кому - то цікаво, хоча це нічого НЕ варто , якщо хто - то може допомогти вирішити stackoverflow.com/questions/31768203 / ...
beefyhalo

2
Схоже, stackoverflow.com/questions/31768203/… вирішено, тож чи можете ви внести свій код і закрити питання власною відповіддю?
Андрій Куба

Відповіді:


17

Я спробую один. Я з радістю прийму кращу відповідь від Тревіса Брауна або Майлза Сабіна.

Nat зараз не можна використовувати для представлення великої кількості

У поточній реалізації Nat, значення відповідає кількості вкладених безформних типів.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]
                 ^

Це може бути використано, наприклад, для застосування одного розміру масиву під час виконання бітових операцій над масивом [байт].


Щойно побачив цю відповідь і +1, це хороший приклад. Варто зазначити, що ви могли надати типи класів, наприклад, наприклад, Shapeless, ops.nat.Sumякі засвідчили б, що два цілі числа типу мають певну суму тощо.
Тревіс Браун

1
Ось приклад Concatкласу типу, який дозволяє об'єднати два рядки рівня типу через макрос. Клас типу для підсумовування цілих рівнів типу може бути, схоже, дуже схожим.
Френк С. Томас

5

Shapeless Natкодує натуральні числа на рівні типу за допомогою кодування Church. Альтернативний метод полягає у поданні натуралів у вигляді типу HList бітів рівня.

Ознайомтеся з густим, який реалізує це рішення у безформному стилі.

Я над цим не працював деякий час, і воно потребує Lazyрозсипання безформних " тут і там", коли Scalac здається, але концепція є твердою :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.