Los foldl
y foldr
funciones son lista- consumidores. Como svenningsson's answer señala correctamente, unfoldr
es un productor de la lista que es adecuado para capturar co -estructura recursiva de fibs
.
Sin embargo, dado que foldl
y foldr
son polimórficos en sus tipos de devolución, es decir, lo que están produciendo al consumir una lista, es razonable preguntar si podrían usarse para consumir una lista y producir otra. ¿Podría alguna de estas listas producidas ser infinita?
En cuanto a la definición de foldl
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f a [] = a
foldl f a (b : bs) = foldl f (f a b) bs
vemos que para foldl
para producir nada en absoluto, la lista que consume debe ser finito. Por lo tanto, si foldl f a
produce salida infinita, es porque a
es infinito o porque f
a veces realiza una generación de lista infinita.
Es una historia diferente con foldr
foldr :: (b -> a -> a) -> a -> [b] -> a
foldr f a [] = a
foldr f a (b : bs) = f b (foldr f a bs)
que no admite la posibilidad de que f
perezoso podría generar alguna salida para cada b
consumida de la entrada. Operaciones como
map g = foldr (\ b gbs -> g b : gbs) [] -- golfers prefer ((:) . g)
stutter = foldr (\ x xxs -> x : x : xxs) []
producen un poco de salida para cada entrada, entregan salida infinita desde la entrada infinita.
Una persona descarada puede expresar cualquier recursión infinita como una foldr
no recursiva en una lista infinita. Por ejemplo,
foldr (\ _ fibs -> 1 : 1 : zipWith (+) fibs (tail fibs)) undefined [1..]
(Editar:. O, para el caso
foldr (\_ fib a b -> a : fib b (a + b)) undefined [1..] 1 1
que está más cerca a la definición en la pregunta)
aunque esta observación, mientras que cierto, no es indicativo de un estilo de programación saludable.
Aunque esto es interesante, en realidad hay una mejor manera de hacer esto que es utilizar la [solución cerrada formulario de búsqueda de los números de Fibonacci] (http : //en.wikipedia.org/wiki/Fibonacci_number#Computation_by_rounding) –
@AndrewWalker, con aritmética de coma flotante, no es una solución exacta. – huon
Tenga en cuenta que en un lenguaje funcional no estricto como Haskell, no hay motivo para evitar la recursión por razones de eficiencia, pero está bien evitarlo por razones de estilo. – AndrewC