2015-07-01 11 views
8

Próbuję zbadać możliwości z udoskonalonymi (i bezkształtnymi), aby poprawić sprawdzanie typu.W jaki sposób użyć wyrafinowanego do wyrażania wiązań ze stałymi> 22

Chciałbym reprezentować, z typem, niektóre ograniczenia interwału lub rozmiaru.

Tak, z wyrafinowane, mogę pisze takie rzeczy:

type Name = NonEmpty And MaxSize[_32] 
type Driver = Greater[_15] 

case class Employee(name : String @@ Name, age : Int @@ Driver = refineLit[Driver](18)) 

Ale chciałbym wyrazić contraints z kasowniki większe.

type BigNumber = Greater[_1000] 

ten nie działa, ponieważ _1000 nie jest zdefiniowana. Ostatnia z nich to: _22 Mogę, z bezkształtnym Succ, zrobić własne, ale jest bardzo uciążliwe.

Przykład:

type _25 = Succ[Succ[Succ[_22]]] 
type _30 = Succ[Succ[Succ[Succ[Succ[_25]]]]] 
type _40 = Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[_30]]]]]]]]]] 
type _50 = Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[_40]]]]]]]]]] 
type _60 = Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[_50]]]]]]]]]] 
type _70 = Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[_60]]]]]]]]]] 
type _80 = Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[_70]]]]]]]]]] 
type _90 = Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[_80]]]]]]]]]] 
type _100 = Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[Succ[_90]]]]]]]]]] 
// etc. 

Czy istnieje lepszy sposób wyrazić takie contraints lub dokonać _1000 w bardziej efektywny sposób? Czy jest coś, co mógłbym przegapić?

Edit:

Próbowałem propozycję Travis:

val thousand = shapeless.nat(1000) 

Ale ta linia powoduje StackOverflowError w czasie kompilacji (w makr) Gdyby spróbować z mniejszą liczbę, jest w porządku.

val limit = shapeless.nat(50) 
type BigNumber = Greater[limit.N] 

case class TestBigNumber(limit : Int @@ BigNumber) 

W moim środowisku, StackOverflowError jest podniesiona dla liczb większych niż 400.

Ponadto, z tego kodu, kompilacja nie zakończyła (używając SBT):

val n_25 = shapeless.nat(25) 
type _25 = n_25.N 

val n_32 = shapeless.nat(32) 
type _32 = n_32.N 

val n_64 = shapeless.nat(64) 
type _64 = n_64.N 
+2

Możesz użyć 'val tys. = Nat (1000); wpisz BigNumber = Greater [thousand.N] ', który jest trochę ładniejszy. Pomyślałem, że można napisać coś w stylu "Nat." 100 "' N ", ale może to sobie wyobraziłem. –

+0

@travis: Mam StackOverflowError podczas ekspansji makra na linii 'val tys. = Nat (1000)', zarówno w zaćmieniu i sbt – volia17

Odpowiedz

10

Greater orzeczenie w refined obsługuje zarówno numery naturalne typu naturalnego typu Shapeless (Nat), jak i typu integlet singleton (udostępniane przez firmę Shapeless's Witness). Więc następujące ograniczenia zrobić to samo:

import eu.timepit.refined.implicits._ 
import eu.timepit.refined.numeric._ 
import shapeless.{ Nat, Witness } 
import [email protected]@ 

val a: Int @@ Greater[Nat._10] = 11 
val b: Int @@ Greater[Witness.`10`.T] = 11 

Ponieważ ze sposobów Nat i typów całkowitą pojedynczych reprezentowane są, te ostatnie są znacznie mniej prawdopodobne, aby przepełnienie stosu kompilatora. Na przykład, następujące prace na moim komputerze:

scala> val c: Int @@ Greater[Witness.`10000`.T] = 10001 
c: [email protected]@[Int,eu.timepit.refined.numeric.Greater[Int(10000)]] = 10001 

chociaż 10000 jest dobrze obok miejsca, w którym rozpoczyna się shapeless.nat(10000) przepełnienie stosu.


jako przypis, możliwe jest korzystanie z reprezentacji Nat dla wartości większych niż 22 bez wpisanie Succ dużo:

val hundred = shapeless.nat(100) 
val c: Int @@ Greater[hundred.N] = 101 

ten trwa nadal dmuchać stos dla dużych wartości, chociaż, więc liczba całkowita typu singleton jest drogą do twojego przypadku.

+0

Dzięki, jest znacznie lepiej. Ale ponieważ zawsze istnieje kod ale, ten kod kompiluje się dobrze z sbt, ale mam błąd w wymagającym 'stabilnym identyfikatorze' '' '' '' eclipse ', ale znaleziono" shapeless.Witness.selectDynamic "(" 32 ")." – volia17

+0

@ volia17 Przepraszam, moja wiedza Eclipse jest prawie nieistniejący i nie mam nic przeciwko utrzymywaniu go w ten sposób. :) Prawdopodobnie warte nowego pytania? –

+1

Aby obejść ten problem, możesz wypróbować 'val tenThousand = Witness. \ 10000 \' ', a następnie' Greater [tenThousand.T] '. –

Powiązane problemy