2012-06-13 18 views
8

¿Cómo puedo hacer esto haskell en F # limpiamente?Versión F # de la coincidencia del patrón de haskell

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

No conozco a Haskell, ¿cuál es el objetivo aquí? Esto parece una optimización que el compilador captará y resolverá. Creo que tratar de escribir un equivalente en F # con la coincidencia de patrones sería más lento. ¿Qué estás intentando lograr? – gjvdkamp

+2

gjvdkamp, ​​no es una optimización, es un dispositivo sintáctico que hace que cada caso sea más fácil de leer. 'f 1 = x; f 2 = y' se traduce a 'f a = caso a de 1 -> x; 2 -> y' - http://www.haskell.org/onlinereport/decls.html#sect4.4.3.1 –

Respuesta

21

No se puede sobrecargar la función en sí, pero se puede utilizar directamente coincidencia de patrones:

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 

uso es el esperado: add 1 2 3

Si usted está dispuesto a utilizar tuplas como argumentos (es decir, renunciar a currying y aplicación parcial), incluso puede escribirlo más abreviado:

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 

Uso actual es: add (1, 2, 3)

+0

¡Gracias! Estaba buscando ejemplos de coincidencia de patrones f # en todas partes y nadie estaba haciendo coincidir más de un parámetro en muestras. Me dieron la impresión de que no podía hacer esto. –

+0

@Jimmy: Técnicamente se está haciendo coincidir una sola tupla aquí, por lo que no te equivocaste ... – ildjarn

+0

@ildjarn: solo en el segundo ejemplo que no es el que usaría porque pierde la aplicación currying/parcial que creo que es una de las partes más beneficiosas de estos idiomas –

8

Recall en Haskell que el general form of functions como una lista de declaraciones con patrones:

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

es el azúcar sólo para el análisis case:

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

por lo la misma traducción se puede hacer a otros idiomas con coincidencia de patrones pero sin patrones de nivel de declaración.

+0

Me doy cuenta que es solo un caso, pero la razón por la cual el azúcar existe en Haskell es por limpieza, esperaba que existiera algo similar en f #, y como yamen señaló, la coincidencia en f # puede funcionar de la misma manera –

5

Esto es puramente sintáctico. Lenguajes como Haskell, ML estándar y Mathematica le permiten escribir a cabo diferentes casos los partidos como si fueran diferentes funciones:

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

mientras que las lenguas como OCaml y F # requieren que usted tenga una única definición de la función y el uso de match o su equivalente en su cuerpo:

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

tenga en cuenta que no tiene que copiar el nombre de la función una y otra vez, con esta sintaxis y se puede factorizar los casos de los partidos más fácilmente:

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

Como yamen escribió, haz currying con let f a b = match a, b with ... en F #.

En la implementación árbol rojo-negro clásico, creo que la duplicación de los nombres de las funciones y los lados derechos de Standard ML y Haskell bastante feas:

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 

en comparación con el equivalente OCaml o 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) 
Cuestiones relacionadas