Funky Haskell lista perezosa recursión implícita
En Haskell, puedes crear listas infinitas debido a la pereza:
Prelude> let g = 4 : g
Prelude> g !! 0
4
Prelude> take 10 g
[4,4,4,4,4,4,4,4,4,4]
Ahora, ¿qué sucede exactamente cuando trato de construir una lista como esta?
Prelude> let f = f !! 10 : f
Prelude> f !! 0
Interrupted.
Prelude> take 10 f
[Interrupted.
Prelude>
losInterrupted.
Me estoy presionando CTRL + C después de esperar unos segundos. Parece entrar en un bucle infinito, pero ¿por qué es así?
Explicación para los no Haskellers:
los:
el operador esprepend
:
Prelude> 4 : [1, 2, 3]
[4,1,2,3]
Esta línea:
Prelude> let g = 4 : g
dice "dejarg
ser la lista construida al anteponer4
en la listag
". Cuando solicita el primer elemento, se devuelve 4, ya que ya está allí. Cuando solicita el segundo elemento, busca el elemento después de 4. Ese elemento sería el primer elemento de la listag
, que acabamos de calcular (4), entonces4
es regresado. El siguiente elemento es el segundo elemento deg
, que nuevamente acabamos de calcular, etc.
!!
solo está indexando en una lista, por lo que esto significa obtener el elemento en el índice0
deg
:
Prelude> g !! 0
4
Pero cuando hago esto:
Prelude> let f = f !! 10 : f
algo se rompe, porque para calcular el primer elemento def
necesitas el undécimo elemento, que aún no existe? Sin embargo, esperaría una excepción, no un bucle infinito ...