How to define a list of recursive calls to a function in Haskell
I like your attempt
ls = 0 : f 0 : f (last ls)
These are the problems with it:
- No type signature. Always write type signatures. They are technically speaking optional, but boy do they help to understand what's going on and what you even want.
- You're trying to apply
f
directly to a list, but it's supposed to operate on list elements. (That's the cause of your error message.) last
on an infinite list can be no good. Anyways this is not what you want:f
should be applied to all elements of the tail instead. That's whatmap
is there for.
So, a correct and complete implementation of that attempt is the following:
iterate' :: (a -> a) -> a -> [a]
-- altn.: (Int->Int) -> [Int], without x₀ but always starting from 0
iterate' f x₀ = ls
where ls = x₀ : f x₀ : map f (tail ls)
N.B. this doesn't actually give [f 0, f (f 0), f (f (f 0)) ..]
but starts from 0
. To start from f 0
, simply remove the standalone x₀
:
iterate' f x₀ = ls
where ls = f x₀ : map f (tail ls)
...which doesn't terminate however (thanks @WillNess), because the tail
would now recurse forever. But you don't actually need tail
! This is the proper definition:
iterate' f x₀ = ls
where ls = f x₀ : map f ls
If you want to define this yourself, vs use iterate as pointed out by @WillemVanOnsem, then simple primitive recursion is your friend:
f :: (a -> a) -> a -> [a]
f g x = let new = g x in new `seq` new : f g new
This is similar to iterate except that iterate starts with the element you provide (the first x
) instead of the first application of the function:
iterate :: (a -> a) -> a -> [a]
iterate f x = x : iterate f (f x)
A self-education can be acquired by hoogling for functions of this type and reading the implementation of any search hits found in the base package.
Haskell has already a function for that: iterate :: (a -> a) -> a -> [a]
. For example:
Prelude> take 10 (iterate (2*) 1)
[1,2,4,8,16,32,64,128,256,512]
Your question is slightly different since the first element should be f 0
, instead of 0
, but we can simply apply f
to it, or use tail :: [a] -> [a]
on the result. For example:
ls :: Num a => (a -> a) -> [a]
ls = tail . flip iterate 0
For example:
Prelude> take 10 (ls (1+))
[1,2,3,4,5,6,7,8,9,10]