0

I have type classes depending on 2 types and one of the type contains the other

sealed trait Version
case class Version1() extends Version
case class Version2() extends Version

case class MyModel1(msg: String, version: Version)
case class MyModel2(msg: String, version: Version)

trait Validate[M, V] {
  def run : Boolean
}

object Validators {
  implicit object ValidateModel1 extends Validate[MyModel1, Version1] {
    override def run: Boolean = true
  }
  implicit object ValidateModel2 extends Validate[MyModel1, Version2] {
    override def run: Boolean = true
  }
}

And I would like to call my type classes this way:

object App {

  def main(args: Array[String]): Unit = {
    val model = MyModel1("Test", Version1())
    validate(model)
  }

  def validate(model: MyModel1) {
    import Validators._    

    val v = implicitly[Validate[MyModel1, model.version.type]]
    v.run
  }
}

But this doesn't work.

Error:(34, 23) could not find implicit value for parameter e: com.playground.Validate[com.playground.MyModel1,model.version.type] val v = implicitly[Validate[MyModel1, model.version.type]] Error:(34, 23) not enough arguments for method implicitly: (implicit e: com.playground.Validate[com.playground.MyModel1,model.version.type])com.playground.Validate[com.playground.MyModel1,model.version.type]. Unspecified value parameter e. val v = implicitly[Validate[MyModel1, model.version.type]]

Replacing the model.version.type with Version1 works

Any idea how to call my type class by pointing to the Version type from the MyModel1 ?

Feel free to suggest a more explicit title :)

Thank you

1 Answer 1

1

Remember that implicits are resolved at compile time so that the compiler cannot know whether inside

case class MyModel1(msg: String, version: Version) 

version is of type Version1 or Version2. It is just not known. If you need to use that information you need to keep it in the signature of your class, either through a generic parameter or an abstract type (which you will use through an helper type that will turn into a generic, so you can use it in signature and express type-relationships)

So the solution is to generify the Model like so

case class MyModel1[V<:Version](msg:String, version:V)
Sign up to request clarification or add additional context in comments.

3 Comments

I have included the import in my test but not in the snippet. Thanks
Oh I totally misunderstood the question. Why are you using model.version.type ? It is a singleton type associated to the field version, are you sure that's what you meant?
It' s something I tried. I thought it returns the type of the version attribute from MyModel . Do you know how I can get the correct type?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.