Why does foldright work for infinite lists? - haskell

I was under the impression that foldright starts from the end of a list and works backwards (this is how I imagined what right-associative means). So I am confused that the following works for infinite lists.
I have a function find:
find :: (a -> Bool) -> List a -> Optional a
find p = foldRight (\c a -> if p c then Full c else a) Empty
Note that the following work:
>> find (const True) infinity
Full 0
I did do some searching and found this post: How do you know when to use fold-left and when to use fold-right?
Unfortunately, the accepted answer is not particularly helpful because the example for right-associative operations is:
A x (B x (C x D))
Which still means it needs to execute the right-most thing first.
I was wondering if anyone can clear this up for me, thanks.

Let's start with a function:
>>> let check x y = if x > 10 then x else y
>>> check 100 5
100
>>> check 0 5
5
check takes two arguments, but might not use its second argument. Since haskell is lazy, this means that the second argument may never be evaluated:
>>> check 20 (error "fire the missles!")
20
This laziness lets us skip a possibly infinite amount of work:
>>> check 30 (sum [1..])
30
Now let's step through foldr check 0 [0..] using equational reasoning:
foldr check 0 [0..]
= check 0 (foldr check 0 [1..]) -- by def'n of foldr
= foldr check 0 [1..] -- by def'n of check
= check 1 (foldr check 0 [2..]) -- by def'n of foldr
= foldr check 0 [2..] -- by def'n of check
-- ...
= foldr check 0 [10..]
= check 10 (foldr check 0 [11..]) -- by def'n of foldr
= foldr check 0 [11..] -- by def'n of check
= check 11 (foldr check 0 [12..]) -- by def'n of foldr
= 11 -- by def'n of check
Note how laziness forces us to evaluate from the top-down, seeing how (and if) the outer-most function call uses its arguments, rather than from the bottom-up (evaluating all arguments before passing them to a function), as strict languages do.

It works because of lazy evaluation. Let’s take a really simple example.
import Data.Char (toUpper)
main :: IO ()
main = interact (foldr capitalized []) where
capitalized :: Char -> String -> String
capitalized x xs = (toUpper x):xs
Run this program interactively and see what happens. The input is an infinite (or at least indefinite) list of characters read from standard input.
This works because each element of the output list gets produced lazily, when it is needed. So the tail is not produced first: it’s only computed if and when it’s needed. Until then, it’s deferred, and we can use the partial results. The partial result for 'h':xs is 'H':(foldr capitalized [] xs). The partial result for 'h':'e':'l':'l':'o':',':' ':'w':'o':'r':'l':'d':'!':'\n':xs is a string we can output before we proceed to the tail xs.
Now see what happens if you try this with foldl.
This works for any data structure that generates a useful prefix. For a reduction operation that produces a single value, and no useful intermediate results, a strict left fold (Data.List.foldl') is usually the better choice.

Your objection proves too much. If it was valid, no infinite lists at all would be possible! An infinite list is constructed using (:). Its second argument, the tail of the list, is also an infinite list, and would have to be evaluated first. This recursively doesn't get us anywhere.

Related

Why doesn't product [0..] evaluate to 0 "instantly"?

I am trying to understand laziness. Because 0 multiplied with any number is 0, shouldn't product [0..] evaluate to 0? I tried also foldl (*) 1 [0..], and to define my own product as
myProduct 0 _ = 0
myProduct _ 0 = 0
myProduct a b = a*b
Why doesn't the fold stop as soon as a 0 is found?
Because the multiply operator doesn't know it's getting chained, and the fold function doesn't know the multiply operator's particular behaviour for any argument. With that combination, it needs to exhaust the list to finish the fold. In fact, for this reason foldl doesn't work at all on infinite lists. foldr does, because it can expand the function from the head of the list.
foldl (*) 1 [0..] -> (((..(((1*0)*1)*2)*3....)*inf
The outermost multiplication in the foldl case can never be found, because the list is infinite. It therefore cannot follow the chain to conclude the result is zero. It can, and does, calculate the product along the list, and that product happens to stay zero, but it will not terminate. If you use scanl instead you can see these intermediate products.
foldr (*) 1 [0..] -> 0*(1*(2*(3*((...((inf*1)))...)))
The outermost multiplication in the foldr case is found immediately, because the rest of the list is in fact left as a lazy thunk. It only runs one step:
foldr (*) 1 [0..] -> 0*(foldr (*) 1 [1..])
So because your custom multiplication operator myProduct is not strict in the second argument if the first argument is zero, foldr myProduct 1 [0..] can terminate.
As a side note, the prelude product function is restricted to finite lists (and may be implemented with foldl). Even if it used foldr, it probably would not shortcut because the standard multiply operator is strict; doing otherwise would be computationally expensive in the common case where the products are neither zero nor chained.
-- sum and product compute the sum or product of a finite list of numbers.
sum, product :: (Num a) => [a] -> a
sum = foldl (+) 0
product = foldl (*) 1
In addition, there's a reason it does not use foldr; as we could see in the expansions and scanl function, the left folds can compute as they consume the list. The right fold, if the operator does not shortcut, needs to build an expression as large as the list itself to even begin computation. This difference is because it's the innermost expression that starts the computation in the strict case, but the outermost expression that produces the result, allowing the lazy case. Lazy vs. non-strict in the Haskell wiki might explain better than I can, and even mentions that pattern matching, which you used to describe the shortcut in myProduct, can be strict.
If you switch the first two lines:
myProduct _ 0 = 0
myProduct 0 _ = 0
myProduct a b = a*b
the second argument will always be evaluated before the first one and the infinite foldr won't work anymore.
Since its impossible to define a myProduct that works lazily for both arguments (not evaluating the second if the first is 0 and not evaluating the first if the second is 0) maybe we are better off with having * always evaluate both its arguments.
You can have it thusly:
myproduct xs = foldr op id xs 1
where
op x r acc = if x==0 then 0 else acc `seq` r (acc*x)
This is a right fold that multiplies the numbers from the left, operating in constant space, and stops as soon as a 0 is encountered.

Why is this tail-recursive Haskell function slower ?

I was trying to implement a Haskell function that takes as input an array of integers A
and produces another array B = [A[0], A[0]+A[1], A[0]+A[1]+A[2] ,... ]. I know that scanl from Data.List can be used for this with the function (+). I wrote the second implementation
(which performs faster) after seeing the source code of scanl. I want to know why the first implementation is slower compared to the second one, despite being tail-recursive?
-- This function works slow.
ps s x [] = x
ps s x y = ps s' x' y'
where
s' = s + head y
x' = x ++ [s']
y' = tail y
-- This function works fast.
ps' s [] = []
ps' s y = [s'] ++ (ps' s' y')
where
s' = s + head y
y' = tail y
Some details about the above code:
Implementation 1 : It should be called as
ps 0 [] a
where 'a' is your array.
Implementation 2: It should be called as
ps' 0 a
where 'a' is your array.
You are changing the way that ++ associates. In your first function you are computing ((([a0] ++ [a1]) ++ [a2]) ++ ...) whereas in the second function you are computing [a0] ++ ([a1] ++ ([a2] ++ ..)). Appending a few elements to the start of the list is O(1), whereas appending a few elements to the end of a list is O(n) in the length of the list. This leads to a linear versus quadratic algorithm overall.
You can fix the first example by building the list up in reverse order, and then reversing again at the end, or by using something like dlist. However the second will still be better for most purposes. While tail calls do exist and can be important in Haskell, if you are familiar with a strict functional language like Scheme or ML your intuition about how and when to use them is completely wrong.
The second example is better, in large part, because it's incremental; it immediately starts returning data that the consumer might be interested in. If you just fixed the first example using the double-reverse or dlist tricks, your function will traverse the entire list before it returns anything at all.
I would like to mention that your function can be more easily expressed as
drop 1 . scanl (+) 0
Usually, it is a good idea to use predefined combinators like scanl in favour of writing your own recursion schemes; it improves readability and makes it less likely that you needlessly squander performance.
However, in this case, both my scanl version and your original ps and ps' can sometimes lead to stack overflows due to lazy evaluation: Haskell does not necessarily immediately evaluate the additions (depends on strictness analysis).
One case where you can see this is if you do last (ps' 0 [1..100000000]). That leads to a stack overflow. You can solve that problem by forcing Haskell to evaluate the additions immediately, for instance by defining your own, strict scanl:
myscanl :: (b -> a -> b) -> b -> [a] -> [b]
myscanl f q [] = []
myscanl f q (x:xs) = q `seq` let q' = f q x in q' : myscanl f q' xs
ps' = myscanl (+) 0
Then, calling last (ps' [1..100000000]) works.

Pairs of elements from list

I want to convert [1,2,3,4] to [[1 2] [2 3] [3 4]] or [(1 2) (2 3) (3 4)]. In clojure I have (partition 2 1 [1,2,3,4]). How can I do it in haskell? I suspect there is such function in standard api but I can't find it.
The standard trick for this is to zip the list with it's own tail:
> let xs = [1,2,3,4] in zip xs (tail xs)
[(1,2),(2,3),(3,4)]
To see why this works, line up the list and its tail visually.
xs = 1 : 2 : 3 : 4 : []
tail xs = 2 : 3 : 4 : []
and note that zip is making a tuple out of each column.
There are two more subtle reasons why this always does the right thing:
zip stops when either list runs out of elements. That makes sense here since we can't have an "incomplete pair" at the end and it also ensures that we get no pairs from a single element list.
When xs is empty, one might expect tail xs to throw an exception. However, because zip
checks its first argument first, when it sees that it's the empty list, the second argument
is never evaluated.
Everything above also holds true for zipWith, so you can use the same method whenever you need to apply a function pairwise to adjacent elements.
For a generic solution like Clojure's partition, there is nothing in the standard libraries. However, you can try something like this:
partition' :: Int -> Int -> [a] -> [[a]]
partition' size offset
| size <= 0 = error "partition': size must be positive"
| offset <= 0 = error "partition': offset must be positive"
| otherwise = loop
where
loop :: [a] -> [[a]]
loop xs = case splitAt size xs of
-- If the second part is empty, we're at the end. But we might
-- have gotten less than we asked for, hence the check.
(ys, []) -> if length ys == size then [ys] else []
(ys, _ ) -> ys : loop (drop offset xs)
Just to throw another answer out there using a different approach:
For n=2 you want to simply zip the list with its tail. For n=3 you want to zip the list with its tail and with the tail of its tail. This pattern continues further, so all we have to do is generalise it:
partition n = sequence . take n . iterate tail
But this only works for an offset of 1. To generalise the offsets we just have to look at the genrated list. It will always have the form:
[[1..something],[2..something+1],..]
So all left to do is select every offsetth element and we should be fine. I shamelessy stole this version from #ertes from this question:
everyNth :: Int -> [a] -> [a]
everyNth n = map head . takeWhile (not . null) . iterate (drop n)
The entire function now becomes:
partition size offset = everyNth offset . sequence . take size . iterate tail
Sometimes is best to roll your own. Recursive functions are what gives LisP its power and appeal. Haskell tries to discourage them but too often a solution is best achieved with a recursive function. They are often quite simple as is this one to produce pairs.
Haskell pattern matching reduces code. This could easily be changed by changing only the pattern to (x:y:yys) to produce (a,b), (c,d), (e,f).
> prs (x:yys#(y:_)) = (x,y):prs yys
> prs "abcdefg"
[('a','b'),('b','c'),('c','d'),('d','e'),('e','f'),('f','g')

Finding the index of a given element using tail recursion

I am trying to write a function to find the index of a given element using tail recursion. Lets say the list contains the numbers 1 through 10, and I am searching for 5, then the output should be 4. The problem I am having is 'counting' using tail recursion. However, I am not even sure if I need to maunally 'count' the number of recursive calls in this case. I tried using !! which does not help because it returns the element in a particular position. I need the the function to return the position of a particular element (the exact opposite).
I have been trying to figure this one out for a hours now.
Code:
whatIndex a [] = error "cannot search empty list"
whatIndex a (x:xs) = foo a as
where
foo m [] = error "empty list"
foo m (y:ys) = if m==y then --get index of y
else foo m ys
Note: I am trying to implement this without using library functions
Your helper function needs an additional parameter for the count.
whatIndex a as = foo as 0
where
foo [] _ = error "empty list"
foo (y:ys) c
| a == y = c
| otherwise = foo ys (c+1)
BTW, it's better form to give this function a Maybe return type instead of using errors. That's how elemIndex works too, for good reason. This would look like
whatIndex a as = foo as 0
where
foo [] _ = Nothing
foo (y:ys) c
| a == y = Just c
| otherwise = foo ys (c+1)
Note: I am trying to implement this without using library functions
This is not a good idea in general. A better exercise is this:
Figure out how to implement it using library functions.
Figure out how to implement whichever library functions you used in step 1 on your own.
This way you're learning three key skills:
What are the standard library functions, and examples of when they are useful.
How to break problems into smaller pieces
How to write basic functions like the ones in the libraries.
In this case, however, your whatIndex is more or less the same function as elemIndex in Data.List, so your problem reduces to writing your own version of this library function.
The trick here is that you want to increment a counter while you recurse down the list. There is a standard technique for writing tail recursive functions, which is called an accumulating parameter. It works like this:
You write an auxiliary function that, compared to the "front-end" function, takes an extra parameter (or more) to keep track of the extra information.
You then define the "real" function as a call to the auxiliary one.
So for elemIndex, the auxiliary function would be something like this (with i as the accumulating parameter for the current element index):
-- I'll leave the blanks for you to fill.
elemIndex' i x [] = ...
elemIndex' i x (x':xs) = ...
Then the "driver" function is this:
elemIndex x xs = elemIndex 0 x xs
But there is a serious problem here that I must mention: getting this function to perform well in Haskell is tricky. Tail recursion is a useful trick in strict (non-lazy) functional languages, but not so much in Haskell, because:
A tail-recursive function in Haskell can still blow the stack,
A non-tail-recursive function can run in constant space.
This older answer of mine shows an example of the second point.
So in your case, a non-tail-recursive solution is probably the easiest one you can give that will run in constant space (i.e., not blow the stack on a long list):
elemIndex x xs = elemIndex' x (zip xs [0..])
elemIndex' x pairs = snd (find (\(x', i) -> x == x') pairs)
-- | Combine two lists by pairing together their first elements, their second
-- elements, etc., until one of the lists runs out.
--
-- EXERCISE: write this function on your own!
zip :: [a] -> [b] -> [(a, b)]
zip xs ys = ...
-- | Return the first element x of xs such that pred x == True. Returns Nothing if
-- there isn't one, Just x if there is one.
--
-- EXERCISE: write this function on your own!
find :: (a -> Bool) -> [a] -> Maybe a
find pred xs = ...

Haskell lazy evaluation

If I call the following Haskell code
find_first_occurrence :: (Eq a) => a -> [a] -> Int
find_first_occurrence elem list = (snd . head) [x | x <- zip list [0..], fst x == elem]
with the arguments
'X' "abcdXkjdkljklfjdlfksjdljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"
how much of the zipped list [('a',0), ('b',1), ] is going to be built?
UPDATE:
I tried to run
find_first_occurrence 10 [1..]
and returns 9 almost instantly, so I guess it does use lazy evaluation at least for simple cases? The answer is also computed "instantly" when I run
let f n = 100 - n
find_first_occurrence 10 (map f [1..])
Short answer: it will be built only up to the element you're searching for. This means that only in the worst case you'll need to build the whole list, that is when no element satisfies the conditions.
Long answer: let me explain why with a pair of examples:
ghci> head [a | (a,b) <- zip [1..] [1..], a > 10]
11
In this case, zip should produce an infinite list, however the laziness enables Haskell to build it only up to (11,11): as you can see, the execution does not diverge but actually gives us the correct answer.
Now, let me consider another issue:
ghci> find_first_occurrence 1 [0, 0, 1 `div` 0, 1]
*** Exception: divide by zero
ghci> find_first_occurrence 1 [0, 1, 1 `div` 0, 0]
1
it :: Int
(0.02 secs, 1577136 bytes)
Since the whole zipped list is not built, haskell obviously will not even evaluate each expression occurring in the list, so when the element is before div 1 0, the function is correctly evaluated without raising exceptions: the division by zero did not occur.
All of it.
Since StackOverflow won't let me post such a short answer: you can't get away with doing less work than looking through the whole list if the thing you're looking for isn't there.
Edit: The question now asks something much more interesting. The short answer is that we will build the list:
('a',0):('b',1):('c',2):('d',3):('X',4):<thunk>
(Actually, this answer is just the slightest bit subtle. Your type signature uses the monomorphic return type Int, which is strict in basically all operations, so all the numbers in the tuples above will be fully evaluated. There are certainly implementations of Num for which you would get something with more thunks, though.)
You can easily answer such a question by introducing undefineds here and there. In our case it is sufficient to change our inputs:
find_first_occurrence 'X' ("abcdX" ++ undefined)
You can see that it produces the result, which means that it does not even look beyond the 'X' it found (otherwise it would have thrown an Exception). Obviously, the zipped list can not be built without looking at the original list.
Another (possibly less reliable) way to analyse your laziness is to use trace function from Debug.Trace:
> let find_first_occurrence elem list = (snd . head) [x | x <- map (\i -> trace (show i) i) $ zip list [0..], fst x == elem]
> find_first_occurrence 'X' "abcdXkjdkljklfjdlfksjdljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"
Prints
('a',0)
('b',1)
('c',2)
('d',3)
('X',4)
4

Resources