This is my first post on SO, and I'm relatively new to Haskell, so please excuse any errors or my code is not idiomatic!
Consider the following two intuitive descriptions: a, f (a), f (f (a)) ...
a. a list containing: a, application f for a, application f for , which , application f for , which ...
B. The list containing the i-th position, I have n attachments f to.
My problem is that I burned out trying to use the iterate
function in Haskell to execute A. My real application is a simulation, but the following contrived example highlights this problem.
import Control.Monad.State example :: State Int [[String]] step :: [String] -> State Int [String] step l = do currentState <- get let result = if (currentState == 1) then "foo":l else "bar":l put (currentState + 1) return result example = do sequence $ take 3 . iterate (>>= step) $ return []
With these definitions
evalState example 1
leads to:
[[],["foo"],["bar","bar"]]
Clearly iterate
does B, not A! Since the step
function only ever adds something to the input list, step ["foo"]
cannot produce ["bar", "bar"]
, regardless of state!
Let me say that I really understand what is happening here, and also that - formally - the result is exactly “as it should be”: step
is a state function, so when f (a) an estimate appears as part of f (f (a )), it will be recounted, and will not be taken from the second element of the list, because the state has changed. I also understand that I could avoid this in my real application by putting my accumulated list inside a state.
However, there are two reasons for posting this post.
First of all, the fact is that iterate
often explained in a way that can potentially mislead a novice to think that he does A when he actually does B. This includes Learn You A Haskell (which I found incredibly useful), but also post SO ( here and here , for example). In fact, the verbal explanation of iterate
in LYAHFGG is almost exactly the definition of A above. Thus, it would be useful to have a message about this, which would be a resource for other Haskell newcomers who get an error because of this and seek an explanation (therefore, by all means, send more accurate, technical, improved wordings, explanations the difference between A and B below).
Secondly, I will still be interested in whether there is a function that actually makes A! In other words, how can I, in the above state example, make a list (with a slight misuse of the notation): [a, b = f (a), f (b), ...]? In other words, given
example2 = do firstResult <- step [] secondResult <- step firstResult return $ [[], firstResult, secondResult]
for which
evalState example2 1
gives the desired result
[[],["foo"],["bar","foo"]]
How to rewrite example2
using iterate
?
A related question has been posted on the Haskell starter list regarding the memoizing version of iterate
. However, this request did not seem to receive a response.
I'm not quite sure that laziness is indeed a problem in my application. Will a strict version of iterate
do what I want? My own, naive, “strict iteration”, as shown below, makes no difference.
iterate' fx = x : rest where previous = fx rest = previous `seq` iterate f previous
Any ideas on all of these would be greatly appreciated!