Pregunta

Estoy tratando de definir un tipo estructural que define cualquier colección que tiene un método "add" (por ejemplo, una colección de Java). El uso de este, quiero definir un par de funciones de orden superior que operan en una determinada colección

object GenericTypes {
  type GenericCollection[T] = { def add(value: T): java.lang.Boolean}
}

import GenericTypes._
trait HigherOrderFunctions[T, CollectionType[X] <: GenericCollection[X]] {
    def map[V](fn: (T) => V): CollectionType[V]
    ....
}

class RichJList[T](list: List[T]) extends HigherOrderFunctions[T, java.util.List]

Esto no se compila con el error siguiente

error: Parameter type in structural refinement may not refer to abstract type defined outside that same refinement 

He intentado eliminar el parámetro de GenericCollection y ponerlo en el método:

object GenericTypes {
  type GenericCollection = { def add[T](value: T): java.lang.Boolean}
}
import GenericTypes._
trait HigherOrderFunctions[T, CollectionType[X] <: GenericCollection]

class RichJList[T](list: List[T]) extends HigherOrderFunctions[T, java.util.List]

pero me sale otro error:

error: type arguments [T,java.util.List] do not conform to trait HigherOrderFunctions's type parameter bounds [T,CollectionType[X] <: org.scala_tools.javautils.j2s.GenericTypes.GenericCollection]

¿alguien puede darme algunos consejos sobre cómo utilizar la tipificación estructural con parámetros con tipo abstractas en Scala? O la forma de lograr lo que estoy buscando lograr? Gracias tanto!

¿Fue útil?

Solución

Como se puede ver en billete 1906 no se puede utilizar el tipo abstracto definida fuera del tipo estructural debido a la falta de información de tipo en tiempo de ejecución.

Esto se afirma en la Scala Language Reference (3.2.7 tipos compuestos) :

Within a method declaration in a structural refinement, the type of
any value parameter may only refer to type parameters or abstract types that are
contained inside the refinement.

La manera habitual de añadir nuevos métodos para un tipo es por conversión de tipo implícito.

trait HigherOrderFunctions[T, CC[_]] {
    def zap[V](fn: () => V): CC[V]
}

class RichJList[T](list: java.util.List[T]) extends HigherOrderFunctions[T, java.util.List]{
    def zap[V](fn: () => V): java.util.List[V] = {
        val l = new java.util.ArrayList[V]
        l add fn()
        l
    }
}
implicit def list2RichList[T](l : java.util.List[T]) = new RichJList(l)
new java.util.ArrayList[AnyRef]() zap (() => 2)

Si el compilador ve que el tipo se perdió el método zap que lo convertirá a un tipo que tiene el método zap con un método de conversión implícita (aquí list2RichList) en su alcance.

scala> new java.util.ArrayList[AnyRef]() zap (() => 2)
res0: java.util.List[Int] = [2]
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top