getText = do
c <- getChar
s <- getText
return (c : s)
main = do
s <- getText
putStr s
What I expect to see is that the input line being echoed each time after I press 'Enter'.
But nothing is echoed ... (I know that this is a infinite loop)
It seems that it won't "return
" until all the "IO" above it are performed. ...
However, the following code:
main = do
s <- getContents
putStr s
It display the line immediately after input.
Given the function getChar
, can I write a getText
that behaves like getContents
?
This can be accomplished with the unsafeInterleaveIO
function from
System.IO.Unsafe
. Your getText
function then becomes
getText = do
c <- getChar
s <- unsafeInterleaveIO $ getText
return (c : s)
Abstracting slightly, we can get a function to generalize this behaviour
lazyDoIO :: IO a -> IO [a]
lazyDoIO act = unsafeInterleaveIO $ do
now <- act
rest <- lazyDoIO act
return (now : rest)
getText = lazyDoIO getChar
Most Haskellers would cringe at doing this, however. If you want to do
incremental stream processing of IO
generated data, it would be much safer
to use a library like Pipes
or Conduits
.