SOLVED: GADT in Scala3: issue "casting" a poymorphic type to a tuple

I have a set of classes that describe rules that can be combined to test some data. I have the following (simplified) definition:

  sealed trait Rule[I]
  case class Input[I](i:I, r:Rule[I]) extends Rule[I]
  case class Proposition[I,R](check: I => Boolean) extends Rule[I]
  case class And[I](r1: Rule[I], r2: Rule[I]) extends Rule[I]
  case class Or[I](r1: Rule[I], r2: Rule[I]) extends Rule[I]

I have a function that matches the above cases takes an input and generates a true/false result. Something like:

    def fold[In,Out](r: Rule[In], data: In, acc: Report, add: (Report, QAResult[_]) => Report): Report =
      def fold[I,O](r: Rule[I], data: I, acc: Report): Report =
        r match
          case Input(d, r) => 
            fold(r, d, acc)
          case Proposition(c) => 
            add(acc, c(data))
          case And(c1, c2) =>
            val r1 = fold(c1, data, acc)
            if r1._2 then fold(c2, data, r1) else r1
          case Or(c1, c2) =>
            val r1 = fold(c1, data, acc)
            if !r1._2 then fold(c2, data, r1) else r1
          case Pair(r1:Rule[_], r2:Rule[_]) =>
            val v1 = data._1
            ???
      fold(r, data, acc)

Now I would like to be able to do something like:

val p = Pair(Proposition(f1), Proposition(f2))

where :

  • p is a Rule[(T1,T2)]
  • f1 is a T1=>Boolean
  • f2 is T2=>Boolean

So I defined:

  case class Pair[I1,I2](r1: Rule[I1], r2: Rule[I2]) extends Rule[(I1,I2)]

The problem is that I do not know how to “cast” the I in the function above to a tuple. I get the error:

[error] 405 |            val v1 = data._1
[error]     |                     ^^^^^^^
[error]     |value _1 is not a member of I
[error]     |
[error]     |where:    I is a type in method fold with bounds >: (I1$1, I2$1) and <: (I1$1, I2$1)

Is this possible?

TIA

Seems like this solves is:

          case Pair(r1:Rule[_], r2:Rule[_]) =>
            val (v1, v2) = data
            ???