2012-06-10 9 views
10

Ich habe mehrere Fragen im Zusammenhang mit Curry-Funktion. Hier frage ich sie eins nach dem anderenCurry-Funktion verwandte Fragen in Scala

1) http://twitter.github.com/scala_school/basics.html gibt ein Beispiel für Curry-Funktion - ich dachte, es ist eine Funktionsdefinition, aber eigentlich ist es nicht. Die REPL erkennt dies nicht als gültige Aussage an.

multiplyThenFilter { m: Int => m * 2 } { n: Int => n < 5} 

2) Warum können wir eine Funktion nicht aus einer partiell parametrisierten Methode definieren? Was ist mit der folgenden Definition falsch?

scala> def multiply(m: Int, n: Int): Int = m * n 
multiply: (m: Int, n: Int)Int 

scala> val timesTwo = multiply(2,_) 
<console>:11: error: missing parameter type for expanded function ((x$1) => multiply(2, x$1)) 
     val timesTwo = multiply(2,_) 
           ^

3) Warum können wir eine teilweise parametrisierte Funktion nicht curried machen? Was ist mit der folgenden Definition falsch?

scala> (multiply(_,_)).curried 
    res13: Int => (Int => Int) = <function1> // THIS IS OK 

scala> (multiply(20,_)).curried 
<console>:12: error: missing parameter type for expanded function ((x$1) => multiply(20, x$1)) 
       (multiply(20,_)).curried 
         ^
+0

1) Es ist ungültig, weil es zuerst deklariert werden muss. Zum Beispiel: 'def multiplyThenFilter (a: Int => Int) (b: Int => Boolean) = {Liste (1,2,3,4) .map (a).filter (b)} –

+0

1) Der multiplyThenFilter ist jetzt weg. Du warst nicht die einzige Person, die davon verwirrt war :-) –

Antwort

11

Frage 1

Das Beispiel Scala Schule ist verwirrend-es ist definitiv keine Definition. Auf GitHub gibt es an issue, also ist es vielleicht ein Fehler. Sie können eine vernünftige Definition vorstellen könnte wie folgt aussehen:

def multiplyThenFilter(f: Int => Int)(p: Int => Boolean): Int => Option[Int] = { 
    i => 
    val j = f(i) 
    if (p(j)) Some(j) else None 
} 

(oder äquivalent f andThen (Some(_) filter p).)

Dann würde das Beispiel eine Funktion sein, die seinen Eingang verdoppelt und gibt das Ergebnis in einem Some wenn es weniger als 5, und None ansonsten. Aber niemand weiß genau, was der Autor beabsichtigt hat, bis es eine Antwort auf dieses Problem gibt.


Frage 2

Der Grund, dass Ihre timesTwo nicht nur funktioniert, ist, dass die Scala-Compiler nicht diese Art von Typ unterstützt this question und my answer there für ein wenig verwandten Detail-Inferenz sehen.

def multiply(m: Int, n: Int): Int = m * n  
val timesTwo = multiply(2, _: Int) 

def multiply(m: Int)(n: Int): Int = m * n  
val timesTwo = multiply(2) _ 

D.h., wenn Sie Typinferenz wollen hier müssen Sie mehrere Parameterlisten verwenden: Sie werden mit einem der folgenden gehen müssen. Ansonsten musst du dem Compiler mit dem Typ helfen.


Frage 3

Für Ihre dritte Frage sei angenommen, wir haben die bekam nach der Ausgabe in Ihrer zweiten Frage zu vermeiden:

val timesTwo = multiply(2, _: Int) 

Dies ist ein Function1, die gerade doesn‘ t haben eine curried Methode-Sie benötigen eine Function2 (oder Function3, etc.) dafür.

Es macht einfach keinen Sinn, über das Curren einer Funktion mit einem einzigen Argument zu sprechen. Curry nimmt eine Funktion mit mehreren Argumenten und gibt Ihnen eine Funktion, die ein einzelnes Argument verwendet, das eine andere Funktion zurückgibt (die möglicherweise ein einzelnes Argument und eine andere Funktion usw. zurückgibt).

+0

sind die zwei Funktionen 'timesTwo' definiert in "val malTwo = multiplizieren (2, _: Int)" und "val malTwo = multiplizieren (2) _" in deiner Antwort zu Frage 2 mit demselben Typ? – chen

+0

Ja, sie sind beide "Int => Int" (oder äquivalent "Function1 [Int, Int]"). –