2017-04-05 2 views
1

Wie kann ich das schaffen? Meine Aufgabe ist ein wenig komplizierter, aber es läuft darauf hinaus, diese nach unten:Scala automatische Art Rückschluss in polymorphe Funktionen

object Z { 
    class B extends Function1[Int, Int] { 
    def apply(i: Int): Int = i 
    } 

    def compose[T <: Function1[X, X], X](fcts: List[T]): Function1[X, X] = { 
    fcts.reduce(_ andThen _) 
    } 

    def test() = { 
    val fcts = List.empty[B] 

    // Unspecified type parameter X 
    val composed: Function1[Int, Int] = compose[B](fcts) 
    } 
} 

Ich weiß nicht, wie die „komponiert“ Funktion definieren zu können, einige konkrete Klasse B empfangen und automatisch schließen, die abhängige Typen X

Antwort

2

Der Scala-Compiler funktioniert nicht gut, wenn Sie versuchen, auf mehrere Ebenen von Typparametern, wie Sie sie haben, zu schließen. Stattdessen wäre es einfacher, T <: Function1[X, X] zu entfernen und einfach einen einzelnen Typparameter zu benötigen, der das Argument und den Rückgabetyp des Function1 darstellt.

def compose[A](fcts: List[Function1[A, A]]): Function1[A, A] = { 
    fcts.reduce(_ andThen _) 
} 

Der Compiler wird eine viel einfachere Zeit einfach haben A Folgern, statt, was mit T und X, um herauszufinden, sind, wenn XT Teil Typ ist.

val a: Int => Int = _ + 10 
val b: Int => Int = _ * 2 
val c: Int => Int = _ - 3 

scala> val f = compose(List(a, b, c)) 
f: Int => Int = scala.Function1$$Lambda$1187/[email protected] 

scala> f(2) 
res1: Int = 21 

Beachten Sie, dass reduce eine Ausnahme für eine leere Liste von Funktionen werfen.

+0

Sicher ist es eine Lösung .. Nicht ganz was ich aber gerne gehabt hätte .. Keine anderen Optionen mit forSome oder anderen Scala Tricks? Die Sache ist, meine Komposition erhält nicht genau eine Liste [B] (oder eine Liste von Funktion1]) .. es ist ein bisschen komplizierter als das .. –

+0

@MichelLemay Sie könnten etwas anderes in einem anderen Fall tun , aber in diesem Fall sehe ich keinen Ausweg aus dem Mangel an Typinferenz. –