scalascala-3match-types

In Scala 3, how to write a term of which type signature is a match type?


Here is a simple example:


    trait RRBound {

      type RR[T]

      def apply[T]: T => RR[T]
    }

    trait Z2 extends RRBound {

      type RR[T] = T match {
        case Option[i] => Seq[i]
      }

      override def apply[T]: T => RR[T] = T match {
        case Option[i] => (v: Option[i]) => v.toSeq
// invalid syntax here
      }
    }

    trait AlsoZ2 {

      def apply[i]: Option[i] => Seq[i] = {v => v.toSeq}
    }

apparently T match can only be used in type definition, so the only way to implement apply[T]: T => RR[T] is by doing it in multiple subtypes, this also means Z2 cannot be converted to AlsoZ2 easily despite that they are functionally identical.

What can be done here to complete Z2 and make AlsoZ2 unnecessary?


Solution

  • Can you make apply inline?

    trait RRBound {
      type RR[T]
      inline def apply[T]: T => RR[T]
    }
    

    Try

    import scala.compiletime.{erasedValue, summonFrom}
    
    override inline def apply[T]: T => RR[T] = (v: T) => summonFrom {
      case given (T =:= Option[i]) => summonFrom {
        case given (Seq[`i`] =:= RR[T]) => (v: Option[`i`]).toSeq
      }
    }
    

    or

    override inline def apply[T]: T => RR[T] = (v: T) => erasedValue[T] match {
      case _: Option[i] => summonFrom {
        case given (T =:= Option[`i`]) => (v: Option[`i`]).toSeq
      }
    }