Domanda

Sto cercando di definire un tipo strutturale che definisce ogni collezione che ha un metodo "add" (per esempio, una collezione java). Usando questo, voglio definire alcune funzioni di ordine superiore che operano su una certa collezione

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]

Questo non compilare con l'errore seguente

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

Ho provato a rimuovere il parametro su GenericCollection e metterlo sul metodo:

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]

ma ottengo un altro errore:

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]

qualcuno può darmi qualche consiglio su come utilizzare la tipizzazione strutturale con i parametri digitati astratte a Scala? O il modo di ottenere quello che sto cercando di realizzare? Grazie mille!

È stato utile?

Soluzione

Come si può vedere nel biglietto 1906 non è possibile utilizzare la tipo astratto definita all'esterno del tipo strutturale a causa di informazioni mancanti tipo a runtime.

Questo è indicato nel Scala di riferimento del linguaggio (3.2.7 tipi composti) :

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.

Il solito modo per aggiungere nuovi metodi a un tipo è quello di conversione di tipo implicita.

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)

Se il compilatore vede che il tipo ha mancato il metodo zap che verrà convertito in un tipo che ha il metodo zap con un metodo di conversione implicita (qui list2RichList) nel campo di applicazione.

scala> new java.util.ArrayList[AnyRef]() zap (() => 2)
res0: java.util.List[Int] = [2]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top