-
Notifications
You must be signed in to change notification settings - Fork 155
/
eval.scala
32 lines (24 loc) · 980 Bytes
/
eval.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package eu.timepit.refined
import eu.timepit.refined.api.Validate
import eu.timepit.refined.eval._
import scala.reflect.runtime.currentMirror
import scala.tools.reflect.ToolBox
import shapeless._
object eval extends EvalValidate {
/** Predicate that checks if a value applied to the predicate `S` yields `true`. */
final case class Eval[S](s: S)
}
private[refined] trait EvalValidate {
// Cache ToolBox for Eval Validate instances
private lazy val toolBox = currentMirror.mkToolBox()
implicit def evalValidate[T, S <: String](
implicit mt: Manifest[T],
ws: Witness.Aux[S]
): Validate.Plain[T, Eval[S]] = {
// The ascription (T => Boolean) allows to omit the parameter
// type in ws.value (i.e. "x => ..." instead of "(x: T) => ...").
val tree = toolBox.parse(s"(${ws.value}): ($mt => Boolean)")
val predicate = toolBox.eval(tree).asInstanceOf[T => Boolean]
Validate.fromPredicate(predicate, _ => ws.value, Eval(ws.value))
}
}