Wieloming
Wieloming

Reputation: 23

Scala nested types with traits

I've got something like this:

trait ObjectId {
  val value: Long
}
case class Room(id: Option[Room.Id])

case object Room {
  case class Id(value: Long) extends ObjectId   
}

case class Tree(id: Option[Tree.Id])

case object Tree {
  case class Id(value: Long) extends ObjectId  
}

What I want to do is create class FromDB with field id, of type which extends trait ObjectId and is nested inside T:

case class FromDB[T](value: T, id)

for example it should work as follows:

FromDB[Room](Room, Room.Id)
FromDB[Tree](Tree, Tree.Id)

Upvotes: 0

Views: 642

Answers (1)

Sandro
Sandro

Reputation: 103

You could use depenent types and let type inference work for you:

trait ObjectId {
    val value: Long
}

trait Model[T] {
    type Id <: ObjectId
}

case class Room(id: Option[Room.Id])

object Room extends Model[Room] {
    case class Id(value: Long) extends ObjectId
}

case class Tree(id: Option[Tree.Id])

object Tree extends Model[Tree] {
    case class Id(value: Long) extends ObjectId
}

case class FromDB[T, I <: Model[T]](value: T, id: I#Id)

val room = Room(Some(Room.Id(1)))

FromDB(room, room.id.get) // compiles
FromDB(room, Tree.Id(123)) // doesn't compile

Here, Model[T] defines a type Id which is constrained to be a child of ObjectId. Each instance of Model[T] has its own implementation of Id.

In FromDB[T, I <: Model[T]], the compiler will infere I if id is an instance of the correct Model[T], it won't compile otherwise.

Upvotes: 1

Related Questions