2010-04-28 18 views
10

Ich versuche, einen Strukturtyp zu definieren, der jede Sammlung definiert, die über eine "add" -Methode verfügt (z. B. eine Java-Sammlung). Mit diesem möchte ich ein paar Funktionen höherer Ordnung definieren, die auf einer bestimmten Sammlung arbeitenVerwenden von Scala-Strukturtypen mit abstrakten Typen

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] 

Das funktioniert nicht mit dem folgenden Fehler kompilieren

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

Ich habe versucht, den Parameter auf GenericCollection entfernen und setzen über die Methode:

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] 

aber ich bekomme einen anderen Fehler:

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] 

Kann mir jemand einen Tipp geben, wie man strukturelle Typisierung mit abstrakten typisierten Parametern in Scala verwendet? Oder wie erreiche ich, was ich erreichen möchte? Vielen Dank!

Antwort

4

Wie Sie in ticket 1906 sehen können, können Sie den abstrakten Typ nicht verwenden, der außerhalb des Strukturtyps aufgrund fehlender Typinformationen zur Laufzeit definiert wird.

Dies ist in den Scala Language Reference (3.2.7 Compound Types) angegeben:

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. 

Der üblicher Weg, um neue Methoden zu einer Art hinzuzufügen, ist durch implizite Typumwandlung.

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) 

Wenn der Compiler sieht, dass die Art die zap Methode verpassten sie es auf eine Art konvertieren, die die zap-Methode mit einer impliziten Konvertierungsmethode (hier list2RichList) in ihrem Umfang hat.

scala> new java.util.ArrayList[AnyRef]() zap (() => 2) 
res0: java.util.List[Int] = [2] 
Verwandte Themen