Depende de lo que quiere decir con generador. La lista se genera de forma lenta, y como nada más hace referencia a ella, las piezas consumidas se recogen de forma casi inmediata. Como el resultado del cálculo anterior no crece, todo el cálculo se ejecuta en espacio constante. Eso no es un requisito del estándar, pero como es más difícil implementar una semántica no estricta con un comportamiento espacial diferente para ese ejemplo (y muchos vagos similares), en la práctica puede confiar en él.
Pero normalmente, la lista todavía se genera como una lista, por lo que se produce una gran cantidad de basura. En circunstancias favorables, ghc elimina la lista [1 .. ]
y produce un bucle no se distribuyen:
result :: [Int]
result = filter odd . filter even $ [1 .. ]
(utilizando las funciones del preludio por pereza), compilados con -O2
genera el núcleo
List.result_go =
\ (x_ayH :: GHC.Prim.Int#) ->
case GHC.Prim.remInt# x_ayH 2 of _ {
__DEFAULT ->
case x_ayH of wild_Xa {
__DEFAULT -> List.result_go (GHC.Prim.+# wild_Xa 1);
9223372036854775807 -> GHC.Types.[] @ GHC.Types.Int
};
0 ->
case x_ayH of wild_Xa {
__DEFAULT -> List.result_go (GHC.Prim.+# wild_Xa 1);
9223372036854775807 -> GHC.Types.[] @ GHC.Types.Int
}
}
Un bucle llanura , que va del 1 al maxBound :: Int
, no produce nada en el camino y []
al final. Es casi lo suficientemente inteligente como para devolver simplemente []
. Tenga en cuenta que solo hay una división por 2, GHC sabe que si un Int
es par, no puede ser impar, por lo que esa verificación se ha eliminado, y en ninguna rama se crea una lista no vacía (es decir, las ramas inalcanzables tienen sido eliminado por el compilador).
¿Se da cuenta de que está utilizando un intérprete para verificar las optimizaciones? – delnan
buen punto, lo compiló, suceden las mismas cosas –
'filter impar. filtrar incluso $ [1 ..] ' – is7s