2010-04-28 16 views
10

Estoy tratando de definir un tipo estructural que define cualquier colección que tenga un método "agregar" (por ejemplo, una colección java). El uso de este, quiero definir un par de funciones de orden superior que operan en una determinada colecciónUso de tipos estructurales Scala con tipos abstractos

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 siguiente error

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

intenté quitar el parámetro de GenericCollection y poniéndolo 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 me puede dar algunos consejos sobre cómo usar el tipado estructural con parámetros abstractos en Scala? ¿O cómo lograr lo que estoy buscando lograr? ¡Muchas gracias!

Respuesta

4

Como puede ver en ticket 1906 no puede usar el tipo abstracto definido fuera del tipo estructural debido a la falta de información de tipo en el tiempo de ejecución.

Esto se afirma en el Scala Language Reference (3.2.7 Compound Types):

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 forma habitual de añadir nuevos métodos a un tipo es mediante la conversión implícita.

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] 
Cuestiones relacionadas