Skip to content

Instantly share code, notes, and snippets.

@michaelt
Created October 7, 2016 02:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michaelt/611d4a28768d088b10982e2a99accdb1 to your computer and use it in GitHub Desktop.
Save michaelt/611d4a28768d088b10982e2a99accdb1 to your computer and use it in GitHub Desktop.
oneShot rule for 'await >>= f'
{-#LANGUAGE BangPatterns #-}
import Pipes
import qualified Pipes.Prelude as P
import Control.Monad.Trans.State.Strict
import GHC.Magic
import qualified Pipes.Internal as I
import Data.IORef
import Control.Monad
await' :: Monad m => Proxy () a y' y m a
await' = await
{-#INLINE [1] await' #-}
yield' :: Monad m => a -> Producer a m ()
yield' = yield
{-#INLINE [1] yield' #-}
{-#RULES
"await' hack" forall f . await' >>= f = I.Request () (oneShot f);
"yield' hack" forall f x . yield' x >>= f = I.Respond x (oneShot f)
#-}
large = 10000000 :: Int
emit :: Int -> Int -> IORef Int -> Producer Int IO ()
emit !large !m ref = do
n <- liftIO (readIORef ref)
when (n < large) $ yield n >> emit large (m+1) ref
receive :: IORef Int -> Consumer Int IO ()
receive ref = do
n <- await
liftIO $ writeIORef ref $! (n+1::Int)
receive ref
receive' :: IORef Int -> Consumer Int IO ()
receive' ref = do
n <- await'
liftIO $ writeIORef ref $! (n+1::Int)
receive' ref
main = do
ref <- newIORef 0
let b = receive' ref
large = 10000000 :: Int
larger = 2*large
runEffect $ emit large 0 ref >-> b
readIORef ref >>= print
runEffect $ emit larger 0 ref >-> b
readIORef ref >>= print
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment