How can I recursively collect a list of things while in the IO monad, and return the list lazily as it's constructed rather than waiting until they've all been collected? Perhaps an example will make things clearer: main = do xs <- getStrings putStrLn (head xs) getStrings = do x <- getLine if x == "stop" then return [] else do xs <- getStrings return (x:xs) How can I make getStrings lazy? main should be able to terminate immediately after I've entered just one line. Amanda ps: This is a fake example, I'm really trying to lazily retrieve answers fetched from an Oracle SQL query.
The following works for me: import IOExts main = do xs <- unsafeInterleaveIO getStrings putStrLn (head xs) getStrings = do x <- getLine if x == "stop" then return [] else do xs <- unsafeInterleaveIO getStrings; return (x:xs) in this particular case, the unsafeInterleaveIO on the recursive call to getStrings isn't necessary, but if you change 'putStrLn (head xs)' to 'mapM_ putStrLn (take 3 xs)' then it's necessary (I believe). HTH - Hal -- Hal Daume III "Computer science is no more about computers | hdaume@isi.edu than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume On Wed, 8 Jan 2003, Amanda Clare wrote:
How can I recursively collect a list of things while in the IO monad, and return the list lazily as it's constructed rather than waiting until they've all been collected?
Perhaps an example will make things clearer:
main = do xs <- getStrings putStrLn (head xs)
getStrings = do x <- getLine if x == "stop" then return [] else do xs <- getStrings return (x:xs)
How can I make getStrings lazy? main should be able to terminate immediately after I've entered just one line.
Amanda
ps: This is a fake example, I'm really trying to lazily retrieve answers fetched from an Oracle SQL query.
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
Hal's solution reminds me of the paper by Levent Erk�k and John Launchbury: Recursive monadic Bindings: Technical Development and Details. http://www.cse.ogi.edu/PacSoft/projects/rmb/mfixTR.pdf One of their examples uses MonadRec and IOExts. webpage: Value recursion in Monadic Computations (a.k.a. Recursive Monadic Bindings) http://www.cse.ogi.edu/PacSoft/projects/rmb/index.html How to use the mdo-notation in Hugs and GHC http://www.cse.ogi.edu/PacSoft/projects/rmb/usage.html Or maybe module Control.Monad.List would be useful. --- Hal Daume III <hdaume@ISI.EDU> wrote:
The following works for me:
import IOExts
main = do xs <- unsafeInterleaveIO getStrings putStrLn (head xs)
getStrings = do x <- getLine if x == "stop" then return [] else do xs <- unsafeInterleaveIO getStrings; return (x:xs)
in this particular case, the unsafeInterleaveIO on the recursive call to getStrings isn't necessary, but if you change 'putStrLn (head xs)' to 'mapM_ putStrLn (take 3 xs)' then it's necessary (I believe).
HTH
- Hal
-- Hal Daume III
"Computer science is no more about computers | hdaume@isi.edu than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume
On Wed, 8 Jan 2003, Amanda Clare wrote:
How can I recursively collect a list of things while in the IO monad, and return the list lazily as it's constructed rather than waiting until they've all been collected?
Perhaps an example will make things clearer:
main = do xs <- getStrings putStrLn (head xs)
getStrings = do x <- getLine if x == "stop" then return [] else do xs <- getStrings return (x:xs)
How can I make getStrings lazy? main should be able to terminate immediately after I've entered just one line.
Amanda
ps: This is a fake example, I'm really trying to lazily retrieve answers fetched from an Oracle SQL query.
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell
===== Christopher Milton cmiltonperl@yahoo.com __________________________________________________ Do you Yahoo!? Yahoo! Mail Plus - Powerful. Affordable. Sign up now. http://mailplus.yahoo.com
I don't think you can do what you want to using standard lists, not without some dirty trickery... But you can define a datatype for such a purpose which would essentially have to put the tail into the Monad. Disadvantage: you would have to redo lots of the list stuff yourself. I had once started writing such a module, it's attached... With this you can write your program as follows: main = do xs <- getStrings putStrLn(headML xs) getStrings = do { x <- getLine; if x=="stop" then return NIL else return (x:<:getStrings) } So, this uses headML instead of head, NIL instead of [], etc. But the things that makes everything work is the different cons-operator, the :<: which allows the list tail to still sit in some monad. Hope this helps Stefan Kahrs
participants (4)
-
Amanda Clare -
Christopher Milton -
Hal Daume III -
S.M.Kahrs