streamly/examples/loops.hs
Harendra Kumar 30a6e32fee Fix Monoid and other instances
Monoid instances should not be derived from underlying type where we want them
to be type specific. Added tests to make sure they are correct.

Other typeclass instances that are dependent on type specific behavior should
also be independently defined rather than derived.

Removed Alternative instances as they are not correct yet.

Removed redundancy by using CPP macros to define instances of different types.
2018-04-22 15:59:09 +05:30

90 lines
3.3 KiB
Haskell

import Streamly
import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
import Streamly.Prelude (nil)
main = do
liftIO $ hSetBuffering stdout LineBuffering
putStrLn $ "\nloopTail:\n"
runStream $ do
x <- loopTail 0
liftIO $ print (x :: Int)
putStrLn $ "\nloopHead:\n"
runStream $ do
x <- loopHead 0
liftIO $ print (x :: Int)
putStrLn $ "\nloopTailA:\n"
runStream $ do
x <- loopTailA 0
liftIO $ print (x :: Int)
putStrLn $ "\nloopHeadA:\n"
runStream $ do
x <- loopHeadA 0
liftIO $ print (x :: Int)
putStrLn $ "\ncoserial:\n"
runStream $ do
x <- (return 0 <> return 1) `coserial` (return 100 <> return 101)
liftIO $ print (x :: Int)
putStrLn $ "\nParallel interleave:\n"
runStream $ do
x <- (return 0 <> return 1) `parallel` (return 100 <> return 101)
liftIO $ print (x :: Int)
where
-------------------------------------------------------------------------------
-- Serial (single-threaded) stream generator loops
-------------------------------------------------------------------------------
-- In a <> composition the action on the left is executed and only after it
-- finished then the action on the right is executed. In other words the
-- actions are run serially.
-- Generates a value and then loops. Can be used to generate an infinite
-- stream. Interleaves the generator and the consumer.
loopTail :: Int -> SerialT IO Int
loopTail x = do
liftIO $ putStrLn "LoopTail..."
return x <> (if x < 3 then loopTail (x + 1) else nil)
-- Loops and then generates a value. The consumer can run only after the
-- loop has finished. An infinite generator will not let the consumer run
-- at all.
loopHead :: Int -> SerialT IO Int
loopHead x = do
liftIO $ putStrLn "LoopHead..."
(if x < 3 then loopHead (x + 1) else nil) <> return x
-------------------------------------------------------------------------------
-- Concurrent (multi-threaded) adaptive demand-based stream generator loops
-------------------------------------------------------------------------------
-- In a <| composition the action on the left is executed first. However,
-- if it is not fast enough to generate results at the consumer's speed
-- then the action on the right is also spawned concurrently. In other
-- words, both actions may run concurrently based on the need.
loopTailA :: Int -> SerialT IO Int
loopTailA x = do
liftIO $ putStrLn "LoopTailA..."
return x `coparallel` (if x < 3 then loopTailA (x + 1) else nil)
loopHeadA :: Int -> SerialT IO Int
loopHeadA x = do
liftIO $ putStrLn "LoopHeadA..."
(if x < 3 then loopHeadA (x + 1) else nil) `coparallel` return x
-------------------------------------------------------------------------------
-- Parallel (fairly scheduled, multi-threaded) stream generator loops
-------------------------------------------------------------------------------
-- In a <|> composition both actions are run concurrently in a fair
-- manner, no one action is preferred over another. Both actions are
-- spawned right away in their own independent threads. In other words, the
-- actions will run concurrently.