haskell - ser - la funcion de relacion en los animales para niños
¿Cómo funciona la función de volteo? (4)
Haskell novato aquí. Estaba pasando por Learn you a haskell, y encontré esta definición de la función flip.
flip'' :: (a -> b -> c) -> (b -> a -> c)
flip'' f = g
where g x y = f y x
Lo que no entiendo es, ¿de dónde vienen x y y? Quiero decir, la firma me dice que flip''
es una función que toma una función (con dos parámetros) y devuelve una función (nuevamente, con dos parámetros).
Si estoy entendiendo esto bien, cuando escribo una función que va como
foo :: (a -> b) -> a -> b
foo f x = f x -- applies the function f on x
Pero entonces, en este caso estoy pasando el parámetro explícitamente [es decir, x
] y entonces puedo acceder a él en el cuerpo de la función. Entonces, ¿cómo es que la función flip''
puede acceder a los parámetros xey?
El Prelude , que está en el paquete base en hackage.haskell.org, se incluye con una importación implícita en cada archivo Haskell donde se encuentra la función de flip . En el lado derecho puede hacer clic en "fuente" y ver el código fuente para voltear .
flip :: (a -> b -> c) -> b -> a -> c
flip f x y = f y x
La cláusula where permite definiciones locales, x=10
y="bla"
. También puede definir funciones localmente con la misma sintaxis que usaría para el nivel superior. add xy = x + y
En la siguiente formulación equivalente hago la sustitución g = fyx
flip :: (a -> b -> c) -> b -> a -> c
flip f x y = g
where
g = f y x
En este momento g no toma parámetros. Pero, ¿y si gab = fba
g como gab = fba
bien entonces tendríamos:
flip :: (a -> b -> c) -> b -> a -> c
flip f x y = g x y
where
g a b = f b a
No, podemos hacer una pequeña cancelación algebraica (si lo piensas como álgebra de la clase de matemáticas estarás bastante seguro). Enfocando en:
flip f x y = g x y
Cancele la y en cada lado para:
flip f x = g x
Ahora cancela la x:
flip f = g
y ahora para ponerlo de nuevo en la expresión completa:
flip :: (a -> b -> c) -> b -> a -> c
flip f = g
where
g a b = f b a
Como último paso estético, podemos hacer la sustitución a
a x
y b
a y
para recuperar la función a nombres de argumento:
flip :: (a -> b -> c) -> b -> a -> c
flip f = g
where
g x y = f y x
Como puede ver, esta definición de flip es un poco redonda y lo que comenzamos en el preludio es simple y es la definición que prefiero. Espero que ayude a explicar cómo funciona y cómo hacer una pequeña manipulación algebraica del código Haskell.
En pocas palabras, también puede definir funciones en un bloque where . Entonces las variables y
son solo los parámetros formales de g
, y es por eso que puedes acceder a él en gxy = fyx
: gxy
define los parámetros formales x
e y
, y fyx
es la definición de lo que g
hace. Finalmente, esa definición se devuelve desde flip f = g
.
Encontremos el tipo de g
.
Sabemos el tipo de volteo: (a -> b -> c) -> (b -> a -> c)
Por lo tanto, podemos deducir el tipo f
: (a -> b -> c)
Tenemos esta definición para g
g x y = f y x
Del lado derecho deducimos que y :: a
y x :: b
.
Por lo tanto, g :: b -> a -> c
Tenga en cuenta que la definición podría reescribirse sin la cláusula ''where''.
flip'' f = g where g x y = f y x
-> flip'' f a b = g a b where g a b = f b a
-> flip'' f a b = f b a
flip''
no tiene acceso a x
y y
. Recibe un argumento f
y evalúa la expresión g
. No x
o y
a la vista.
Sin embargo, g
es en sí mismo una función, definida con una ecuación auxiliar en la cláusula where
de flip''
.
Puedes leer gxy = fyx
exactamente como si fuera una ecuación de nivel superior como flip''
. Entonces g
es una función de dos argumentos, x
e y
. Es g
que tiene acceso a y
, no flip''
. Los valores para esos argumentos no existen hasta que se aplica g
, que no es hasta después de que flip''
haya devuelto la función g
(si es que alguna vez).
Lo que es especial acerca de que g
esté definido en la cláusula where
de flip''
es que puede tener acceso a los argumentos de flip''
, que es cómo g
se puede definir en términos de f
.
Entonces cuando se invoca flip''
recibe una función f
. Para cada invocación particular de flip''
, construye una nueva función g
. g
recibiría dos argumentos, x
e y
, cuando se llama, pero eso aún no ha sucedido. flip''
luego devuelve g
como resultado.