Generating a list of values that only depend on the previous value is a typical application for the unfoldr
function (Data.List.unfoldr
):
import Data.List (unfoldr)
collatzList = unfoldr nextCollatz
where nextCollatz n | n <= 0 = Nothing
| n == 1 = Just (1,0)
| even n = Just (n, n `quot` 2)
| otherwise = Just (n, 3*n+1)
unfoldr f x0
takes a starting value x0
, and applies a function f
to it. If f x0
is Nothing
, the algorithm terminates; if it is Just (push, next)
, it adds push
to the result list, and uses next
as the new value for x0
. Another example, generating squares up to 100 using unfoldr:
import Data.List (unfoldr)
squareList = unfoldr pow2
where pow2 n | n > 100 = Nothing
| otherwise = Just (n, 2*n)
-- "Add n to the result list,
-- start next step at 2*n."
(And the obligatory remark about error
: it's usually better to make the function return some dummy value. In my Collatz function above for example, the result for non-positive integers is an empty list instead of an exception.)