Skip to content

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)