
Hello! On Mon, Mar 19, 2001 at 06:43:55PM +0100, Andreas Gruenbacher wrote:
On Mon, 19 Mar 2001, Simon Peyton-Jones wrote:
Lazy evaluation *is* coroutines, in a way.
What I had in mind was something like the following (pseudocode), which could easily be implemented on top of coroutines:
class Channel c t where send :: t -> c -> IO () receive :: c -> IO t
sender :: Int -> Channel -> ... sender n receiver = do send n receiver return (sender (n+1) receiver)
receiver :: Channel -> ... receiver sender = do i <- receive sender return (receiver sender)
c :: Channel Int c = ...
main = run_them [ sender 1 c, receiver c ]
Now, you can do this: sender :: Int -> [Int] sender n = n:(sender (n+1)) receiver :: [Int] -> () receiver (x:xs) = receiver xs main = let sent_stuff = sender 1 receiver_result = receiver sent_stuff in receiver_result `seq` return () I.e. lazy lists work like coroutine channels often enough. You can do that a bit more abstractly: send :: a -> [a] -> [a] send = (:) receive :: (a -> [a] -> result) -> [a] -> result receive f (x:xs) = f x xs sender n = send n $ sender (n+1) receiver = receive $ \received_thing -> receiver main = (as above) Note that the definition of sender now looks not too unsimilar to your monadic things: sender n = send n >> sender (n+1) === sender n = do send n sender (n+1) -- your 'return' above is redundant receiver = receive >>= \received_thing -> receiver === receiver = do received_thing <- receive receiver Now, in fact, you could achieve this effect with a continuation+state monad quite well (state for input, continuation as *one* way for lazy output).
[...]
Kind regards, Hannah.