Is there a lazy IO Monad session?

You have a sequence of actions that prefer to be performed in chunks due to some highly reliable overhead, such as packet headers or connections. The limit is that sometimes the next action depends on the result of the previous one, in which case all pending actions are performed immediately.

Example:

mySession :: Session IO ()
    a <- readit  -- nothing happens yet
    b <- readit  -- nothing happens yet
    c <- readit  -- nothing happens yet
    if a       -- all three readits execute because we need a
      then write "a"
      else write "..."
    if b || c  -- b and c already available
      ...

It reminds me of so many Haskell concepts, but I can't put it on it.

Of course, you could do something obvious, like:

[a,b,c] <- batch([readit, readit, readit])

But I would like to hide the fact of chunking from the user for use.

Not sure if Session is the right word. Maybe you can offer the best? (Packet, Batch, Chunk, and Deferred come to mind.)

Update

, , , , , . ?

+4
3

, , , , , haskell , a , b c, seq .

, , >>, :

data Session m a = Session { pending :: [ m () ], final :: m a }                    

runSession :: Monad m => Session m a -> m a                                         
runSession (Session ms ma) = foldr (flip (>>)) (return ()) ms >> ma                            

instance Monad m => Monad (Session m) where                                         
  return = Session [] . return                                                      
  s >>= f = Session [] $ runSession s >>= (runSession . f)                          
  (Session ms ma) >> (Session ms' ma') =
    Session (ms' ++ (ma >> return ()) : ms) ma'

, - :

 liftIO :: IO a -> Session IO a  
 liftIO = Session []             

 exampleSession :: Session IO Int
 exampleSession = do             
   liftIO $ putStrLn "one"       
   liftIO $ putStrLn "two"       
   liftIO $ putStrLn "three"     
   liftIO $ putStrLn "four"      
   trace "five" $ return 5       

ghci> runSession exampleSession
five
one
two
three
four
5
ghci> length (pending exampleSession)
4
+3

unsafeInterleaveIO. , , , , .

:

lazyReadits :: IO [a]
lazyReadits = unsafeInterleaveIO $ do
  a <- readit
  r <- lazyReadits
  return (a:r)

unsafeInterleaveIO , , , . , : readit , - , . mapM unsafeInterleaveIO (replicate 3 readit) , readit , , , , , unsafeInterleaveIO .

0
source

All Articles