
I also tried
t15 = let grabby = unlines . takeWhile (not . blank) . lines top = ("first time: " ++) . grabby . ("second time: " ++) . grabby in interact top
but that didn't work either:
thartman@ubuntu:~/haskell-learning/lazy-n-strict>runghc sequencing.hs a first time: second time: a b b
If someone can explain the subtleties of using interact when you run out of stdio here, it would be nice to incorporate this into
Essentially, what's happening here is that interact consumes *all* of standard input, and runs your function on it. This means that as you've realised here, your function must do *all* of the processing of input in one go – but this is good! This means our IO is restricted to one tiny little corner of the program, and we get to write pure Haskell everywhere else :) What's going on with your top function on the other hand is that (.) is not `after` in the sense you're thinking. If you want one grabby to consume some of the input, but not all of it you'd need to return a pair containing the output, and the unconsumed input.
where it talks about how using interact is the easy way to approach these types of problems. Not *that* easy though, as this scenario suggests.
The key here is that it's more composable than using IO – IO can change all kinds of wierd state, and result in two functions doing totally different things depending on when they're called. This means you can't reliably stick bits of IO code together. With pure functional code though, referential transparency guarentees that you can. Bob