„Kann nicht existentiell abstrakt über parametrisierte Typ ...“
Frage
Ich war Messing mit Scala 2.8 zum Spaß um und versuchen, ein Zuhälter
val array:Array[T]
val list:List[T] = array.as[List]
Also hier ist, was ich versucht zu tun:
object Test {
abstract class NatTrans[F[_], G[_]] {
def convert[T](f:F[T]):G[T]
}
implicit def array2List:NatTrans[Array, List] = new NatTrans[Array, List] {
def convert[T](a:Array[T]) = a.toList
}
// this next part gets flagged with an error
implicit def naturalTransformations[T, F[_]](f:F[T]) = new {
def as[G[_]](implicit n:NatTrans[F, G]) = n convert f
}
}
jedoch die Definition von naturalTransformations
mit dem Fehler angezeigt "kann nicht existentiell abstrakt über parametrisierte Typen G [T]" . Um dies zu beheben, kann ich umschreiben naturalTransformations
zusammen mit einer zusätzlichen Klasse Transformable
etwa so:
class Transformable[T, F[_]](f:F[T]) {
def as[G[_]](implicit n:NatTrans[F, G]) = n convert f
}
implicit def naturalTransformations[T, F[_]](f:F[T]) = new Transformable[T, F](f)
und es scheint zu funktionieren. Aber es scheint, wie mein erster Versuch sollte gleichwertig war, so dass ich neugierig bin, warum es fehlgeschlagen ist und was die Fehlermeldung bedeutet.
Lösung
Meine Vermutung wäre, dass dies, weil aufgrund ist auf folgende Aussagen in der Spezifikation, § 6.11, Blöcke:
Ein lokal definierten Typdefinition Typ t = T wird durch die existenzielle Klausel gebunden Typ t> T <: T. Es ist ein Fehler, wenn t Typ Parameter führt.
Und ein struktureller Beispiel Schöpfung Ausdruck zu einem Block ausgewertet wird, so
new {def greet{println("hello")}}
ist eine Abkürzung für
{ class anon$X extends AnyRef{ def greet = println("hello") }; new anon$X }
so wertet sie zu einem Block Ausdruck (nach § 6.10 der SPEC), mit der zuvor erwähnten Einschränkung. Warum diese Einschränkung ist, da weiß ich nicht, aber. Der Fehler, der ausgelöst wird, kann in der TYPERS Klasse unter dieser Ort , das scheint zu bestätigen, dass diese Einschränkung die Ursache des Fehlers ist, dass Sie zu sehen. Wie Sie erwähnt haben, in einer Klasse die Funktion codiert, entfernt den Block Ausdruck Einschränkung:
scala> class N[M[_]]
defined class N
scala> class Q { def as[M[_]](n:N[M]) = null}
defined class Q
scala> new { def as[M[_]](n:N[M]) = null}
:7: error: can't existentially abstract over parameterized type M
new { def as[M[_]](n:N[M]) = null}
Andere Tipps
Das klingt für mich wie eine Einfachheit gegen Allgemeinheit Fall: Es könnte eine neue Variablen vom Typ jedes Mal erzeugt werden, um ein Block erstellt wird, einige Typkonstruktor Erfassung mit existentiellem Typ instanziiert, aber das wäre eine Fehlerdiagnose schwieriger verständlich machen.
Beachten Sie auch, dass eine Klasse mit dem Anruf in einem schnellen invokevirtual dreht, anstatt Berufung auf als () Methode durch Reflexion.