For a service that handle a lot of ided entities, I'm trying to have some strong typing. To achieve this I'm using a technique based on phantom types/tagged type as it can be found in shapeless or scalaz. (I don't want to use AnyVal because I really don't want to pay the cost of boxing/unboxing)
I've done a minimal exemple which hit the following compile error :
class type required but String with controllers.TestController.Tagged[controllers.MyId] found
Here are the files :
- app/controllers/TestController.scala
package controllers
import javax.inject._
import controllers.TestController.TString
import play.api.mvc._
trait MyId
object TestController {
trait Tagged[U]
type TString[T] = String with Tagged[T]
def TString[T](s: String) = s.asInstanceOf[String with Tagged[T]]
implicit def tStringPathBindable[T](implicit binder : PathBindable[String]) : PathBindable[TString[T]] =
binder.transform(TString,identity)
}
@Singleton
class TestController @Inject() extends Controller {
def index(id : TString[MyId]) = Action { implicit request =>
Ok("")
}
}
conf/routes
GET /myroute/:id controllers.TestController.index(id : TString[MyId])
The build.sbt
name := """play-tag"""
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.11.11"
// Adds additional packages into conf/routes
play.sbt.routes.RoutesKeys.routesImport ++=
Seq(
"controllers.MyId",
"controllers.TestController._"
)
project/build.properties
sbt.version=0.13.15
project/plugins.sbt
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.14")
Is there a way to fix this error ? if no what is the reason ? corollary question, what would be the best practice to achive what I'm trying to do ? For instance I'm not very happy with the fact that I'm exposing that the Id is composed of a string but I don't want to much boilerplate either as I have a lot of entities to deal with.