This will work, but it could require an awful lot of repetitious code, depending on the specifics of your application:
trait A {
def name: String
}
case class B(override val name: String) extends A
case class C(override val name: String) extends A
trait CanCopy[T] {
def copy(t: T, newName: String): T
}
implicit object canCopyB extends CanCopy[B] {
override def copy(b: B, newName: String) = b.copy(name=newName)
}
implicit object canCopyC extends CanCopy[C] {
override def copy(c: C, newName: String) = c.copy(name=newName)
}
def newALike[T <: A](instance: T)(implicit ev: CanCopy[T]): T =
ev.copy(instance, instance.name + "_new")
The problem is that trait A can't know the specifics of how to construct an instance of a descendant class. As the Scala compiler sees it, there is no telling what you might define as an extension of trait A, or what arguments its constructor might take. CanCopy and the implicit objects tell the Scala compiler "This is how you construct a B, and this is how you construct a C." The implicit argument's name is ev, to stand for "evidence": it tells the compiler to look for evidence that the type T can be copied, and that evidence is supplied by an object that can do the job.
Depending on your application, you might be able to avoid some repetitious code by defining another trait, which extends A, and which B and C extend, which guarantees that a .copy method with specific arguments will be available. Then you could have a single implicit object, of type CanCopy[ThatIntermediaryTrait], which knows to call the .copy method.