Closed soronpo closed 6 years ago
On second look I think this may not be required. Bounding implicit conversion to ValueOf (or any other boxing) and creating a separate definition for every use-case, allows me to implement this with a one-time-hassle.
implicit def toValueOfInt[T <: Int](t : T) : ValueOf[T] = new ValueOf[T](t)
implicit def toValueOfXInt[T <: XInt](t : T) : ValueOf[T] = new ValueOf[T](t)
type CompileTime[C] = Require[ITE[IsNotLiteral[C], true, C]]
type RunTime[R] = SafeBoolean[IsNotLiteral[R]]
def smallerThan50[T <: Int](rw : ValueOf[T])
(implicit ct_check: CompileTime[T < 50], rt_check : RunTime[T]) : Unit = {
if (rt_check) require(rw.value < 50, "")
}
var forty = 40
var sixty = 60
smallerThan50(40) //passes compile-time check
smallerThan50(forty) //passes run-time check
smallerThan50(60) //fails compile-time check
smallerThan50(sixty) //fails run-time check
scala> smallerThan50(40) //passes compile-time check
scala> smallerThan50(forty) //passes run-time check
scala> smallerThan50(60) //fails compile-time check
<console>:18: error: could not find implicit value for parameter ct_check: CompileTime[60 < 50]
smallerThan50(60) //fails compile-time check
^
scala> smallerThan50(sixty) //fails run-time check
java.lang.IllegalArgumentException: requirement failed:
at scala.Predef$.require(Predef.scala:293)
at .smallerThan50(<console>:20)
... 37 elided
@milessabin I'll leave this to you to close the issue or not. This is a good-enough alternative for my use-case.
I'll just add my solution for this issue, as TwoFace
values added for the singleton-ops library.
https://contributors.scala-lang.org/t/twoface-values-closing-the-gap-between-run-compile-time-functionality/869
Again, feel free to close this issue.
A useful discussion, but I think we should close for now and revisit later if need be.
Following a conversation started on gitter, I suggest we allow
ValueOf[T]
to accept non-singleton values.Motivation We can have unified functions for both literal and non-literal of the same type (e.g,
Int
andInt with Singleton
), and those can impose either compile-time or run-time constraints. Following is an example that will be possible to implement using singleton-ops, if this issue is resolved.CompileTime[C]
succeeds to return an implicit if and only ifC
is not a literal orC
istrue
.RunTime[R]
always returns an implicit value that can be implicitly converted toBoolean
and indicates ifR
is not a literal type (and should be checked at run-time).Consequently, we will be able to run the following:
Singleton type bounds Additionally, we may need some kind of way to signal the compiler to accept only singleton-type values. Perhaps a unified upper bound like
<: AnySingleton
, which is equivalent totype AnySingleton = Int with Singleton | String with Singleton | Double with Singleton | ...
In dotty this can be potentially defined as-is, but in scalac the compiler would handle the unification artificially.