In addition to other answers with a bigger perspective: with lazy lists, using foldl' in a function that returns a list is usually a bad idea. foldl' often useful when you reduce a list to a strict (non-fuzzy) scalar value (for example, by summing a list). But when you build a list as a result, foldr usually better, because of laziness; constructor : lazy, so the tail of the list is not computed until it is needed.
In your case:
newList_foldr lst = foldr (\x acc -> x*2 : acc) [] lst
This is actually the same as map (*2) :
newList_foldr lst = map (*2) lst map f lst = foldr (\x acc -> fx : acc) [] lst
Assessment (using the first map -less definition):
newList_foldr [1..10] = foldr (\x acc -> x*2 : acc) [] [1..10] = foldr (\x acc -> x*2 : acc) [] (1:[2..10]) = 1*2 : foldr (\x rest -> fx : acc) [] [2..10]
This is something like Haskell will evaluate when newList [1..10] forced. He evaluates only further if the consumer requires this result, and only as much as necessary to satisfy the consumer. For example:
firstElem [] = Nothing firstElem (x:_) = Just x firstElem (newList_foldr [1..10])
It also means that newList based on newList can work with infinite lists:
newList_foldr [1..] = [2,4..] firstElem (newList_foldr [1..]) = 2
If you use foldl' , on the other hand, you should always evaluate all lists, which also means that you cannot work with infinite lists:
firstElem (newList_good [1..]) -- doesn't terminate firstElem (newList_good [1..10]) = firstElem (foldl' (\acc x -> x*2 : acc) [] [1..10]) = firstElem (foldl' (\acc x -> x*2 : acc) [] (1:[2..10])) = firstElem (foldl' (\acc x -> x*2 : acc) [2] [2..10]) -- we can't short circuit here because the [2] is "inside" the foldl', so -- firstElem can't see it = firstElem (foldl' (\acc x -> x*2 : acc) [2] (2:[3..10])) = firstElem (foldl' (\acc x -> x*2 : acc) [4,2] [3..10]) ... = firstElem (foldl' (\acc x -> x*2 : acc) [18,16,14,12,10,8,6,4,2] (10:[])) = firstElem (foldl' (\acc x -> x*2 : acc) [20,18,16,14,12,10,8,6,4,2] []) = firstElem [20,18,16,14,12,10,8,6,4,2] = firstElem (20:[18,16,14,12,10,8,6,4,2]) = Just 20
The foldr based algorithm performed 4 steps to compute firstElem_foldr (newList [1..10]) , while about 21 steps were taken on the basis of foldl' . Worse, 4 steps are a constant value, while 21 is proportional to the length of the input list - firstElem (newList_good [1..150000]) takes 300 001 steps, and firstElem (newList_foldr [1..150000] takes 5 steps, like firstElem (newList_foldr [1..] , for that matter.
Note that firstElem (newList_foldr [1.10]) works in constant space as well as in constant time (it should: you need more than constant time to allocate more than constant space). The truism from strict languages ββ- " foldl is tail recursive and works in constant space, foldr not tail recursive and works in linear space or worse" - is not true in Haskell.