In Scala 3 program I have several case classes that share a lengthy function that only differs slightly for each class, so it makes sense to make it generic. But here's the problem: I cannot come up with the solutions that will directly return a collection of a correct type without resorting to an ugly hack like asInstanceOf.
I simplified the code for a readability purpose:
enum TestStructure:
case Struct1(v1: Int)
case Struct2(v2: Int)
@tailrec def testNotWorking[T <: TestStructure](l: List[T], acc: List[T] = Nil): List[T] = l match
case Nil => acc.asInstanceOf[List[T]].reverse
case (s: Struct1) :: t =>
testNotWorking(t, s.copy(v1 = s.v1 + 1) :: acc)
case (s: Struct2) :: t =>
testNotWorking(t, s.copy(v2 = s.v2 + 1) :: acc)
@tailrec def testWorking[T <: TestStructure](l: List[T], acc: List[TestStructure] = Nil): List[T] = l match
case Nil => acc.asInstanceOf[List[T]].reverse
case (s: Struct1)::t =>
test(t, s.copy(v1 = s.v1 + 1)::acc)
case (s: Struct2) :: t =>
test(t, s.copy(v2 = s.v2 + 1) :: acc)
testWorking[Struct1](List(Struct1(1), Struct1(2))
Declaring acc as List[T] doesn't work here. Is there any way to solve this problem without runtime casting?