2012-06-13 8 views
8

Wie mache ich diese Haskell in F # sauber?F # Version von Haskell Muster passen

add 1 2 x = 3 + x 
add 1 x y = 1 + x + y 
add z x y = z + x + y 
+0

Ich weiß nicht, Haskell, was ist das Ziel hier? Dies sieht wie eine Optimierung aus, die der Compiler auffangen und lösen würde. Ich denke, dass ein Versuch, ein Äquivalent in F # mit Mustervergleich zu schreiben, langsamer wäre. Was versuchst du zu erreichen? – gjvdkamp

+2

gjvdkamp, ​​es ist keine Optimierung, es ist ein syntaktisches Gerät, das jeden Fall einfacher zu lesen macht. 'f 1 = x; f 2 = y 'wird übersetzt in' f a = Fall a von 1 -> x; 2 -> y' - http://www.haskell.org/onlinereport/decls.html#sect4.4.3.1 –

Antwort

21

Sie können nicht die Funktion Überlastung selbst, aber Sie können Muster direkt passend verwenden:

let add z x y =    // curried multiple parameters 
    match z, x, y with  // convert to three-tuple to match on 
    | 1, 2, x -> 3 + x 
    | 1, x, y -> 1 + x + y 
    | z, x, y -> z + x + y 

Verwendung als erwartet: add 1 2 3

Wenn Sie bereit sind, zu verwenden, Tupel als Argumente (dh verzichten auf Currying und teilweise Anwendung), können Sie sogar mehr Kurzschrift schreiben:

let add =      // expect three-tuple as first (and only) parameter 
    function     // use that one value directly to match on 
    | 1, 2, x -> 3 + x 
    | 1, x, y -> 1 + x + y 
    | z, x, y -> z + x + y 

Verbrauch ist jetzt: add (1, 2, 3)

+0

Danke! Ich suchte überall nach f # Muster-Übereinstimmungs-Beispielen und niemand passte mehr als einen Parameter in Samples an, ich bekam den Eindruck, dass man das nicht tun konnte. –

+0

@Jimmy: Technisch gesehen wird hier ein einzelnes Tupel gefunden, also haben Sie sich nicht geirrt ... – ildjarn

+0

@ildjarn: nur im zweiten Beispiel, das nicht das ist, was ich verwenden würde, weil Sie currying/teilweise Anwendung verlieren, die ich fühle, ist einer der nützlichsten Teile dieser Sprachen –

8

Recall in Haskell, dass die general form of functions als eine Liste von Erklärungen mit Mustern:

f pat1 ... = e1 
f pat2 ... = e2 
f pat3 ... = e3 

ist nur Zucker für die case Analyse:

f x1 .. xn = case (x1, .. xn) of 
       (pat1, ..., patn) -> e1 
       (pat2, ..., patn) -> e2 
       (pat3, ..., patn) -> e3 

so Die gleiche Übersetzung kann in andere Sprachen mit Mustervergleich, aber ohne Muster auf Deklarationsebene, erfolgen.

+0

Ich weiß, es ist nur ein Fall, aber der Grund, dass der Zucker in Haskell existiert, ist für Sauberkeit, ich hatte gehofft, dass etwas ähnliches in f # existiert, und wie Yamen darauf hingewiesen, kann die Anpassung in f # auf die gleiche Weise funktionieren –

5

Dies ist rein syntaktisch. Sprachen wie Haskell, Standard ML und Mathematica können Sie verschiedene Spiel Fällen schreiben, als ob sie verschiedene Funktionen waren:

factorial 0 = 1 
factorial 1 = 1 
factorial n = n * factorial(n-1) 

während Sprachen wie OCaml und F # Sie benötigen eine einzige Funktionsdefinition haben und match oder gleichwertige Verwendung in sein Körper:

let factorial = function 
    | 0 -> 1 
    | 1 -> 1 
    | n -> n * factorial(n-1) 

Hinweis, dass Sie zu den Funktionsnamen über nicht kopieren und immer wieder mit dieser Syntax und Sie können Match Fälle leichten Faktor:

let factorial = function 
    | 0 | 1 -> 1 
    | n -> n * factorial(n-1) 

Wie Yamen schrieb, currying mit let f a b = match a, b with ... in F #.

Im klassischen Rot-Schwarz-Baum Umsetzung finde ich die Vervielfältigung der Funktionsnamen und rechten Seiten in Standard ML und Haskell ziemlich hässlich:

balance :: RB a -> a -> RB a -> RB a 
balance (T R a x b) y (T R c z d) = T R (T B a x b) y (T B c z d) 
balance (T R (T R a x b) y c) z d = T R (T B a x b) y (T B c z d) 
balance (T R a x (T R b y c)) z d = T R (T B a x b) y (T B c z d) 
balance a x (T R b y (T R c z d)) = T R (T B a x b) y (T B c z d) 
balance a x (T R (T R b y c) z d) = T R (T B a x b) y (T B c z d) 
balance a x b = T B a x b 

im Vergleich zu dem äquivalenten OCaml oder F #:

let balance = function 
    | B, z, (T(R, y, T(R, x, a, b), c) | T(R, x, a, T(R, y, b, c))), d 
    | B, x, a, (T(R, z, T(R, y, b, c), d) | T(R, y, b, T(R, z, c, d))) -> 
     T(R, y, T(B, x, a, b), T(B, z, c, d)) 
    | a, b, c, d -> T(a, b, c, d)