Another way to do this is to use the shapeless library and use Nat . The limitation is that you will need to create instances of Foo at compile time, mostly with known constants.
import shapeless.ops.nat_ import shapeless.nat._ case class Foo[T <: Nat](numberOfFoo: Int)(implicit ev: GT[T, _0] object Foo { // The problem is this won't work. def apply[T <: Nat](n: Int): Foo[T] = Foo(Nat(n)) }
This will only work when used as follows:
Foo(_1)
Where _1 comes from shapeless.nat._ . If you move on to implementation, part 0 is forced, even if you don't matter formless:
if (n < 0) c.abort(c.enclosingPosition, s"A Nat cannot represent $n")
Stick to simpler things
This, however, is rather cumbersome, because whatever approach you choose, it will rely on the macro, and macros cannot work if the value is not known at compile time . This can become very limited if the easier delegation method no longer works.
In practice, it may be more efficient to use this approach and use conventional methods. Regardless of whether you use the formless or sophisticated library mentioned above, the story does not change, so for normal use it is probably cleaner to perform a validation check.
source share