In Haskell I can easily define a recursive function which takes a value and returns a string:
Prelude> let countdown i = if (i > 0) then (show i) ++ countdown (i-1) else ""
Prelude> countdown 5
"54321"
I want to use the same kind of design to read available data from a file handle. In this particular case I need to read the data in the same fashion as hGetContents, but without leaving the handle in the “semi-closed” state, so that I can loop interaction with stdin/stdout handles of a process opened with createProcess:
main = do
-- do work to get hin / hout handles for subprocess input / output
hPutStrLn hin "whats up?"
-- works
-- putStrLn =<< hGetContents hout
putStrLn =<< hGetLines hout
where
hGetLines h = do
readable <- hIsReadable h
if readable
then hGetLine h ++ hGetLines h
else []
Gives the error:
Couldn't match expected type `IO b0' with actual type `[a0]'
In the expression: hGetLine h : hGetLines h
I know there are various libraries available for accomplishing what I’m trying to accomplish, but sice I’m learning my question is really how to perform recursive IO. TIA!
Naive solution, strict and O(n) stack
You still have to use the do-notation, which would lead to this:
But see my comment, this version of
hGetLinesis too strict!Lazy, streaming version
It won’t return your list, until it has all the input. You need something a bit lazier. For this, we have
unsafeInterleaveIO,Now you can start streaming results line-by-line to your consumer code: