es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Recuperando el tipo Singleton de un tipo Higher Kinded en Scala 3

Estoy contribuyendo a una biblioteca de Scala 3 que realiza verificación de tipo en tiempo de compilación y me he encontrado con el siguiente problema.

Tengo una jerarquía de tipos como esta:

trait Match[V <: String]
type Alphanumeric = Match["^[a-zA-Z0-9]+"]
trait RegexChecker[MatchType] {
    inline def checkRegex(text: String): Boolean
}
inline given RegexChecker[Alphanumeric] with {
    inline def checkRegex(text: String): Boolean = ???
}

En el RegexChecker implícito me gustaría extraer el patrón regex del tipo Alphanumeric y usarlo para realizar cálculos, desafortunadamente no encuentro una manera de hacerlo. Debido a que todo es solo un tipo, no puedo pasar Alphanumeric como esto def extractor[T](dummy: Match[T]) para extraerlo usando constValue. Estuve investigando sobre los macros e intenté hacer coincidir mi tipo de esta manera:

def extractorMacro()(using Quotes, Type[T]): Expr[String] = {
    import quotes.reflect.*

    val tpe = TypeRepr.of[T]

    val r = tpe.asType match 
      case '[ Match[v] {type Match$V = a } ] => ???
      case '[ Match[String] { type V = q }] => ???
      case _ => "fail"
}

Pero desafortunadamente ninguno de los casos funciona a pesar de compilar correctamente (el ejemplo de ScalaDoc para valueOfConstant no funciona realmente, porque no tengo Expr, solo tengo Type).

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Como experto en IT especializado en scala, scala-macros y scala-3, el problema que estás encontrando está relacionado con la extracción del patrón regex del tipo Alphanumeric en el RegexChecker implícito. Dado que Alphanumeric es solo un tipo, no se puede pasar al método extractor para extraer utilizando constValue. Has intentado usar macros para resolver el problema haciendo coincidir el tipo, pero ninguno de los casos funciona, a pesar de compilar correctamente.

    Una posible solución para este problema podría ser usar un parámetro de tipo en la interfaz Match para pasar el patrón regex al tipo Alphanumeric. Por ejemplo:

    trait Match[V <: String, P <: String]:
      val pattern: P 
    
    type Alphanumeric[P <: String] = Match[^[a-zA-Z0-9]+$, P]
    
    inline given RegexChecker[P <: String](using pattern: ValueOf[P]) with
      inline def checkRegex(text: String): Boolean = text.matches(pattern.value)
    

    En esta solución, la interfaz Match ahora toma dos parámetros de tipo: V, que debe ser un subtipo de String, y P, que también debe ser un subtipo de String. El tipo Alphanumeric ahora toma un parámetro de tipo P, que se utiliza para pasar el patrón regex a la interfaz Match.

    En la instancia dada de RegexChecker, el parámetro de tipo P se utiliza para inferir el valor del patrón utilizando ValueOf. El método checkRegex ahora utiliza el método matches para comparar el texto con el patrón regex.

    Esta solución te permite extraer el patrón regex del tipo Alphanumeric y utilizarlo para cálculos en el RegexChecker implícito.

Comments are closed.