Zależy od tego, co rozumiemy przez generator. Lista jest generowana leniwie, a ponieważ nic innego nie wskazuje na to, zużyte części są prawie natychmiast zbierane. Ponieważ wynik powyższego obliczenia nie wzrasta, całe obliczenie przebiega w stałej przestrzeni. Nie jest to wymagane przez normę, ale ponieważ trudniej jest zaimplementować nieistotną semantykę o różnych zachowaniach przestrzennych dla tego przykładu (i wiele niejasno podobnych), w praktyce można na niej polegać.
Ale zwykle lista jest nadal generowana jako lista, więc powstało dużo śmieci. W sprzyjających warunkach ghc eliminuje listę [1 .. ]
i tworzy pętlę dla realokacji:
result :: [Int]
result = filter odd . filter even $ [1 .. ]
(z wykorzystaniem funkcji Prelude OUT lenistwo), utworzonych z -O2
generuje rdzeń
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
}
}
zwykły pętli , działa od 1 do maxBound :: Int
, nie produkując niczego po drodze i []
na końcu. Jest prawie na tyle sprytny, aby powrócić do zwykłego powrotu: []
. Zauważ, że istnieje tylko jeden podział o 2, GHC wie, że jeśli Int
jest równy, nie może być nieparzysty, więc kontrola została wyeliminowana, aw żadnym oddziale nie jest tworzona niepusta lista (tj. Nieosiągalne gałęzie mają zostały usunięte przez kompilator).
Czy zdajesz sobie sprawę, że używasz interpretera do sprawdzania optymalizacji? – delnan
Dobra rada, skompilowałem to, te same rzeczy się zdarzają –
'filter odd. filtruj nawet $ [1 ..] ' – is7s