I had written the simple program below, convinced it would absorb all keystrokes I hit and, when I hit q, it would print the previous keys as a single string.
import System.IO
main = do
hSetBuffering stdin NoBuffering
hSetEcho stdin False
x <- takeWhile (/= 'q') <$> sequence (repeat getChar)
print x
But that's not the case.
It's not that keys are not read, as it's obvious when I change the longest line to
x <- takeWhile (/= 'q') <$> sequence (repeat (getChar >>= \c -> print c >> return c))
which does print the characters one by one as I type them; but the q doesn't cause the loop to exit.
My understanding is that sequence is not lazy, in the sense that it will try to run the infinite list of getChar actions before takeWhile has a chance to start its job.
If that's the case, then what other options do I have?
If the intent is clear form the snippet above, I can add that in the real application getChar would be swapped with a function that does c <- getChar and then makes a processing on it.
You may consider a little helper action for that purpose:
This would enable you to get
xlikeor with some other appropriate default value instead of
' '.If you truly want a one-liner, you can always use
fixto convert any recursive action into a lambda expression.First, then,
and then