on master help sign in
Update tutorial with zip types & composition summary
commitfa3d53dc11f5f9ab50472f731c0beb840109810d authorHarendra Kumar <harendra.kumar@gmail.com> dateThu 30 Nov 2017, 15:48 (9 years ago) parent29cffbe
1 file changed+107−12
src/Streamly/Tutorial.hs+107−12
src/Streamly/Tutorial.hs+107−12
@@ -91,6 +91,12 @@ module Streamly.Tutorial
9191 -- * Zipping Streams
9292 -- $zipping
9393
94+ -- ** Serial Zipping
95+ -- $serialzip
96+
97+ -- ** Parallel Zipping
98+ -- $parallelzip
99+
94100 -- * Concurrent Programming Examples
95101 -- $concurrent
96102
@@ -587,6 +593,10 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
587593-- total 17 seconds (1 + 3 + 4 + 2 + 3 + 4):
588594--
589595-- @
596+-- import Streamly
597+-- import Streamly.Prelude
598+-- import Control.Concurrent
599+--
590600-- s1 = d 1 <> d 2
591601-- s2 = d 3 <> d 4
592602-- d n = delay n >> return n
@@ -655,10 +665,89 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
655665-- Folds
656666
657667-- $compositionSummary
658−-- Summary of compositions
668+--
669+-- The following table summarizes the types for monadic compositions and the
670+-- operators for sum style compositions. This table captures the essence of
671+-- streamly.
672+--
673+-- @
674+-- +-----+--------------+------------+
675+-- | | Serial | Concurrent |
676+-- +=====+==============+============+
677+-- | DFS | 'StreamT' | 'AsyncT' |
678+-- | +--------------+------------+
679+-- | | '<>' | '<|' |
680+-- +-----+--------------+------------+
681+-- | BFS | 'InterleavedT' | 'ParallelT' |
682+-- | +--------------+------------+
683+-- | | '<=>' | '<|>' |
684+-- +-----+--------------+------------+
685+-- @
659686
660687-- $zipping
661−-- Applicative composition, Parallel applicative
688+--
689+-- Zipping is a special transformation where the corresponding elements of two
690+-- streams are combined together using a zip function producing a new
691+-- stream of outputs. Two different types are provided for serial and
692+-- concurrent zipping. These types provide an applicative instance that zips
693+-- the argument streams.
694+
695+-- $serialzip
696+--
697+-- 'StreamZip' zips streams serially:
698+--
699+-- @
700+-- import Streamly
701+-- import Streamly.Prelude
702+-- import Control.Concurrent
703+--
704+-- d n = delay n >> return n
705+-- s1 = adapt . serially $ d 1 <> d 2
706+-- s2 = adapt . serially $ d 3 <> d 4
707+--
708+-- main = (toList . zipping $ (,) \<$> s1 \<*> s2) >>= print
709+-- @
710+--
711+-- This takes total 10 seconds to zip, which is (1 + 2 + 3 + 4) since
712+-- everything runs serially:
713+--
714+-- @
715+-- ThreadId 29: Delay 1
716+-- ThreadId 29: Delay 3
717+-- ThreadId 29: Delay 2
718+-- ThreadId 29: Delay 4
719+-- [(1,3),(2,4)]
720+-- @
721+
722+-- $parallelzip
723+--
724+-- 'AsyncZip' zips streams concurrently:
725+--
726+-- @
727+-- import Streamly
728+-- import Streamly.Prelude
729+-- import Control.Concurrent
730+-- import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
731+--
732+-- d n = delay n >> return n
733+-- s1 = adapt . serially $ d 1 <> d 2
734+-- s2 = adapt . serially $ d 3 <> d 4
735+--
736+-- main = do
737+-- liftIO $ hSetBuffering stdout LineBuffering
738+-- (toList . zippingAsync $ (,) \<$> s1 \<*> s2) >>= print
739+-- @
740+--
741+-- This takes 7 seconds to zip, which is max (1,3) + max (2,4) because 1 and 3
742+-- are produced concurrently, and 2 and 4 are produced concurrently:
743+--
744+-- @
745+-- ThreadId 32: Delay 1
746+-- ThreadId 32: Delay 2
747+-- ThreadId 33: Delay 3
748+-- ThreadId 33: Delay 4
749+-- [(1,3),(2,4)]
750+-- @
662751
663752-- $concurrent
664753--
@@ -671,6 +760,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
671760--
672761-- @
673762-- import Streamly
763+-- import Streamly.Prelude (toList)
674764-- import Data.List (sum)
675765--
676766-- main = do
@@ -684,11 +774,13 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
684774--
685775-- @
686776-- import Streamly
777+-- import Streamly.Prelude (toList)
687778-- import Data.List (sum)
688779--
689780-- main = do
690−-- z \<- toList $ asyncly $ foldMapWith (\<|) (\\x -> return $ x * x) [1..100] >>= \\xsq ->
691−-- foldMapWith (\<|) (\\x -> return $ x * x) [1..100] >>= \\ysq ->
781+-- z \<- toList $ asyncly $ do
782+-- xsq \<- foldMapWith (\<|) (\\x -> return $ x * x) [1..100]
783+-- ysq \<- foldMapWith (\<|) (\\x -> return $ x * x) [1..100]
692784-- return $ sqrt (xsq + ysq)
693785-- print $ sum z
694786-- @
@@ -698,6 +790,8 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
698790-- Let us see a reactive programming example:
699791--
700792-- @
793+-- {-\# LANGUAGE FlexibleContexts #-}
794+--
701795-- import Streamly
702796-- import Control.Concurrent (threadDelay)
703797-- import Control.Monad (when)
@@ -706,7 +800,7 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
706800--
707801-- data Event = Harm Int | Heal Int | Quit deriving (Show)
708802--
709−-- userAction :: MonadIO m => AsyncT m Event
803+-- userAction :: MonadIO m => StreamT m Event
710804-- userAction = cycle1 $ liftIO askUser
711805-- where
712806-- askUser = do
@@ -716,15 +810,15 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
716810-- "quit" -> return Quit
717811-- _ -> putStrLn "What?" >> askUser
718812--
719−-- acidRain :: MonadIO m => AsyncT m Event
813+-- acidRain :: MonadIO m => StreamT m Event
720814-- acidRain = cycle1 $ liftIO (threadDelay 1000000) >> return (Harm 1)
721815--
722−-- game :: (MonadAsync m, MonadState Int m) => AsyncT m ()
816+-- game :: (MonadAsync m, MonadState Int m) => StreamT m ()
723817-- game = do
724818-- event \<- userAction \<|> acidRain
725819-- case event of
726−-- Harm n -> modify $ \h -> h - n
727−-- Heal n -> modify $ \h -> h + n
820+-- Harm n -> modify $ \\h -> h - n
821+-- Heal n -> modify $ \\h -> h + n
728822-- Quit -> fail "quit"
729823--
730824-- h <- get
@@ -732,9 +826,10 @@ import Control.Monad.Trans.Class (MonadTrans (lift))
732826-- liftIO $ putStrLn $ "Health = " ++ show h
733827--
734828-- main = do
735−-- putStrLn "Your health is deteriorating due to acid rain,\
736−-- \ type \"potion\" or \"quit\""
737−-- runStateT (runStreaming $ serially $ game) 60
829+-- putStrLn "Your health is deteriorating due to acid rain,\\
830+-- \\ type \\"potion\\" or \\"quit\\""
831+-- _ <- runStateT (runStreamT game) 60
832+-- return ()
738833-- @
739834
740835-- $statemachine