Try Tuple for solving
import Playground.TupleProcessor.given_ResultProcess_*:
import Playground.TupleProcessor.given_ResultProcess_EmptyTuple
import Playground.AtomProcess.given_BaseProcess_Atom
enum Atom[T]:
case IntAtom(x: Int) extends Atom[Int]
case BoolAtom(x: Boolean) extends Atom[Boolean]
case IntVectorAtom(x: Vector[Int]) extends Atom[Vector[Int]]
trait BaseProcess[A]:
def baseProcess(a: A): A
def f[T](a: Atom[T]): Atom[T] = a match
case Atom.BoolAtom(x) => Atom.BoolAtom(!x)
case Atom.IntAtom(x) => Atom.IntAtom(x + 1)
case Atom.IntVectorAtom(x) => Atom.IntVectorAtom(x.map(_ + 1))
object AtomProcess:
given [T]: BaseProcess[Atom[T]] with
def baseProcess(a: Atom[T]) = f(a)
trait ResultProcess[A]:
def process(x: A): A
object TupleProcessor:
given ResultProcess[EmptyTuple] with
def process(x: EmptyTuple) = x
given [H: BaseProcess, T <: Tuple: ResultProcess]: ResultProcess[H *: T] with
def process(x: H *: T) = summon[BaseProcess[H]]
.baseProcess(x.head) *: summon[ResultProcess[T]].process(x.tail)
def fTuple[X <: Tuple : ResultProcess](tuple: X) = summon[ResultProcess[X]].process(tuple)
val (a, b, c) = fTuple((Atom.IntAtom(1), Atom.BoolAtom(true), Atom.IntVectorAtom(Vector(1, 2, 3))))
println(a)
println(b)
println(c)