Saltar al contenido

Ejemplo de función recursiva de Haskell con foldr

Solución:

una función que toma un argumento y devuelve un valor booleano. Dado que el operador> es en realidad una función infija, el primer argumento en el ejemplo anterior parece el resultado de una aplicación parcial a la función>, ¿es esto correcto?

sí: (>10) es la abreviatura de x -> x > 10, Tal como (10>) sería corto para x -> 10 > x.

un valor no especificado del mismo tipo esperado como el argumento faltante para la función proporcionada como primer argumento

en primer lugar, no es un argumento faltante: al omitir un argumento, se obtiene un valor de función. sin embargo, el tipo del segundo argumento coincide con el argumento de la función >10, al igual que coincide con el tipo de los elementos de la lista [10,20,30,40] (que es un mejor razonamiento).

una lista de valores del tipo mencionado anteriormente

si.

Pero la función real primero que parece estar definida de manera diferente a su declaración de tipo, con un solo argumento. Dado que foldr normalmente toma tres argumentos que reuní, está ocurriendo algún tipo de aplicación parcial. A la expresión lambda proporcionada como argumento para foldr también parece que le faltan sus argumentos.

eso es porque dado eg foo x y z = x * y * z, estas 2 líneas son equivalentes:

bar x     = foo x
bar x y z = foo x y z

– eso se debe a un concepto llamado curry. Currying es también la razón por la que las firmas de tipo de función no son (a, b) -> c pero en vez a -> b -> c, que a su vez es equivalente a a -> (b -> c) debido a la asociatividad correcta del -> operador de tipo.

Por tanto, estas dos líneas son equivalentes:

firstThat f     = foldr (x acc -> if f x then x else acc)
firstThat f x y = foldr (x acc -> if f x then x else acc) x y

Nota: que también puedes usar Data.List.find combinado con Data.Maybe.fromMaybe:

λ> fromMaybe 2000 $ find (>10) [10, 20, 30]
20
λ> fromMaybe 2000 $ find (>10) [1, 2, 3]
2000

Ver también:

  • https://en.wikipedia.org/wiki/Currying.
  • https://www.fpcomplete.com/user/EFulmer/currying-and-partial-application
  • http://learnyouahaskell.com/higher-order-functions

Pero la función real firstThat parece estar definido de manera diferente a su declaración de tipo, con un solo argumento. Ya que foldr normalmente toma tres argumentos que reuní, hay algún tipo de aplicación parcial.

Tienes razón. Sin embargo, hay una forma más agradable de expresarlo que hablar de “argumentos perdidos”, una que no te lleve a preguntar a dónde se han ido. Aquí hay dos formas en las que no faltan los argumentos.

En primer lugar, considere esta función:

add :: Num a => a -> a -> a
add x y = x + y

Como sabrás, también podemos definirlo así:

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

Eso funciona porque las funciones de Haskell son valores como cualquier otro. Simplemente podemos definir un valor, add, como igual a otro valor, (+), que resulta ser una función. No se requiere una sintaxis especial para declarar una función. El resultado es que escribir argumentos explícitamente (casi) nunca es necesario; la razón principal por la que lo hacemos porque a menudo hace que el código sea más legible (por ejemplo, podría definir firstThat sin escribir el f parámetro explícitamente, pero no lo haré porque el resultado es bastante espantoso).

En segundo lugar, siempre que vea un tipo de función con tres argumentos …

firstThat :: (a -> Bool) -> a -> [a] -> a

… también puedes leerlo así …

firstThat :: (a -> Bool) -> (a -> [a] -> a)

… es decir, una función de un argumento que produce una función de dos argumentos. Eso funciona para todas las funciones de más de un argumento. La conclusión clave es que, en el fondo, todas las funciones de Haskell toman solo un argumento. Es por eso que la aplicación parcial funciona. Así que al ver …

firstThat :: (a -> Bool) -> a -> [a] -> a
firstThat f = foldr (x acc -> if f x then x else acc)

… puede decir con precisión que ha escrito explícitamente todos los parámetros que firstThat toma – es decir, solo uno 🙂


La expresión lambda proporcionada como argumento para foldr Parece que también faltan sus argumentos.

Realmente no. foldr (cuando está restringido a listas) es …

foldr :: (a -> b -> b) -> b -> [a] -> b

… y entonces la función que se le pasa toma dos argumentos (siéntase libre de agregar comillas de aire alrededor de “dos”, dada la discusión anterior). La lambda se escribió como …

x acc -> if f x then x else acc

… con dos argumentos explícitos, x y acc.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *