2011-01-21 6 views
5
uncurry f=\(a,b)->f a b 

uncurry convierte una función curry a una función en pares, pero la función anterior simplemente la convierte en una función de curry f a b. ¿Eso no contradice la definición de la función uncurry?tipo de firma de la función uncurry

Respuesta

13

Lo que Pelotom y Chuck dijeron es 100% correcto. Creo que en algún momento te confundiste un poco acerca de las definiciones de Curry vs Uncurry y Function.


Sabemos que una función al curry es una como:

add x y = x + y

Se sería definición:

add :: (Num a) => a -> a -> a

Agregar toma una Num, y devuelve una función que toma un Num y retu rns a Num.

Al tener de esta manera, podemos obtener una aplica parcialmente función, como

add3 = add 3

Gracias a add siendo al curry, cuando podemos pasar un solo parámetro (en este caso, 3) , podemos recuperar una función que toma un Num y devuelve un Num.

>add3 5 
8 

funciones Uncurried toma tuplas, o valores agrupados juntos, como (1,2). (Tenga en cuenta que las tuplas no tienen pares. Puede tener una tupla de la forma de (1,2,3,4,5).Solo ofertas regulares y poco frecuentes con pares específicamente). Si cambiamos nuestro añadir a ser uncurried, sería:

add :: (Num t) => (t, t) -> t 
add (x, y) = x + y 

que toma una tupla de dos Num s y devuelve un Num. No podemos aplicarlo parcialmente como lo hicimos con add como función curried. Necesita ambos parámetros, pasados ​​en una tupla.

¡Ahora, en la función de descabezar! (Si desea conocer el tipo de una función, use :t <some function> en GHCi, o use Hoogle).

uncurry :: (a -> b -> c) -> ((a, b) -> c) 
uncurry f=\(a,b)->f a b 

Entonces, ¿qué sabemos de esto? Se necesita f, que observamos en la definición es una función curried de (a-> b-> c), y devuelve función no ejecutada ((a, b) -> c).

Si alimentamos uncurry nuestro curried add (recuerde: add x y), ¿qué obtenemos?

obtenemos una función anónima o función lambda, que toma una tupla, y aplica los valores de la tupla, y ab, a nuestra función, add.

f a b no significa que obtenemos una función: verá un -> si ese fuera el caso. Acabamos de obtener el valor de f con a y b.

Es algo así como si lo hiciéramos esto a mano:

tupleAdd (a,b) = add a b

Pero uncurry significa todo para nosotros, y que sólo puede continuar a lo largo de nuestra marca nueva forma uncurried de nuestra función originalmente al curry.

Cool, hunh?

3

Creo que está malinterpretando. De hecho devuelve una función en pares. Eso es lo que significa la parte \(a,b)-> - define una función anónima que toma un par y realiza la función dada en los valores en ese par.

6

Otra forma de escribir esta definición por lo que es más claro lo que está pasando sería:

uncurry :: (a -> b -> c) -> (a, b) -> c 
uncurry f = \(a, b) -> (f a) b 

La variable f tiene tipo a -> b -> c, es decir, es una función de curry, y uncurry g para alguna función al curry g tiene el tipo (a, b) -> c, es decir, una función no ejecutada.

recordar que cuando x y y son términos medios, x yaplica la función x a y. Y f a b (o (f a) b) significa aplicar la función f al argumento a, produciendo una función del tipo b -> c, a continuación, aplicar inmediatamente esta función para b, produciendo un resultado de tipo c. De modo que el lado derecho de esta definición simplemente muestra cómo desempaquetar los componentes de un argumento tuple y aplicarlos a una función curried, ¡que es exactamente el proceso de desmantelamiento!

5

Puede escribir una función que se comporta de la misma manera (y con la misma firma) sin lambda:

uncurry' :: (a -> b -> c) -> ((a, b) -> c) 
uncurry' f (a,b) = f a b 

Creo que esta versión es más fácil de leer. Si tiene un tupel y una función que toma dos valores únicos (o más exactos, que toma un valor y devuelve una función que toma el siguiente valor), la función de descifrado 'hace el "desenvolvimiento" de la tupla para nosotros.

En general, si ves algo como

f x y z = x + y + z 

que es lo mismo que

f = \x y z -> x + y + z 

o

f x = \y -> (\z -> x + y + z) 
Cuestiones relacionadas