How to choose typeclass by dynamic input in Scala
116
Solution 1
I think, your problem is that Map
is a wrong way to represent this.
Use a case class:
case class Foo(
name: Rep[Option[String]],
email: Rep[String],
score: Rep[Int]
)
def applyRater[T : Rater](t: T) = implicitly[Rater[T]](t)
def rate(foo: Foo, what: String) = what match {
case "name" => applyRater(foo.name)
case "email" => applyRater(foo.email)
case "score" => applyRater(foo.score)
case _ => default
}
Solution 2
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(FormCollection collection)
{
string valueFromNameTextBox = collection["name"];
}
You can index into this collection with the names of all the inputs on the form.
Author by
Kotofey
Updated on December 19, 2022Comments
-
Kotofey over 1 year
Have a slick table with columns:
def name: Rep[Option[String]] = ??? def email: Rep[String] = ??? def fraudScores: Rep[Int] = ???
also there is typeclass to calcualte rate for different fields:
trait Rater[T] { def apply(rep: T): Result } object Rater { def getRater[T](t: T)(implicit rater: Rater[T]): Result = rater(t) implicit val int: Rater[Rep[Int]] = v => calculateRate(v, _) implicit val str: Rater[Rep[String]] = v => calculateRate(v, _) implicit val strOpt: Rater[Rep[Option[String]]] = v => calculateRate(v, _) }
and map:
val map: Map[String, Rep[_ >: Option[String] with String with Int]] = Map( "name" -> name, "email" -> email, "scores" -> fraudScores )
what I'd like to do is getting correct instance based on dynamic input, like:
val fname = "scores" // value getting from http request map.get(fname).fold(default)(f => { val rater = getRater(f) rater(someVal) })
but getting error that there is no implicit for
Rep[_ >: Option[String] with String with Int]
, is there some workaround for this? -
Kotofey about 3 yearsHey, thanks for answer! I can see one disadvantage of this approach - every time someone change the type of field in table it have to not forget to change type of field also in case class. Would love to see if it can be done without this.
-
Dima about 3 years@kotofey, well I am not familiar with slick, but perhaps there is a way to just use the ORM class directly instead of additional case class? Also you don't really jave to remember to change the type in the case class: it simply will not compile if you forget.
-
Kotofey about 3 yearsyou're right it - will not compile, so it is a possible solution. But in case if there is a lot of fields in
Foo
and also need to have more than one functions likerate
it looks not so good and would be really good to reduce boilerplate.