mirror of
https://github.com/composewell/streamly.git
synced 2024-09-17 14:37:27 +03:00
Move examples from Streamly module to examples dir
This commit is contained in:
parent
f3dbbde613
commit
c5f97f0e3b
@ -121,7 +121,7 @@ matrix:
|
|||||||
|
|
||||||
# Note COVERALLS (hpc-coveralls) works only with cabal build.
|
# Note COVERALLS (hpc-coveralls) works only with cabal build.
|
||||||
# For this to succeed you have to add your project to coveralls.io first
|
# For this to succeed you have to add your project to coveralls.io first
|
||||||
- env: BUILD=cabal CABALVER=2.0 GHCVER=8.2.2 COVERALLS_OPTIONS="--coverage-mode=StrictlyFullLines --exclude-dir=test test properties"
|
- env: BUILD=cabal CABALVER=2.0 GHCVER=8.2.2 COVERALLS_OPTIONS="--coverage-mode=StrictlyFullLines --exclude-dir=test test properties loops nested-loops parallel-loops"
|
||||||
addons: {apt: {packages: [cabal-install-2.0,ghc-8.2.2], sources: [hvr-ghc]}}
|
addons: {apt: {packages: [cabal-install-2.0,ghc-8.2.2], sources: [hvr-ghc]}}
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
-- This example is adapted from Gabriel Gonzalez's pipes-concurrency package.
|
-- This example is adapted from Gabriel Gonzalez's pipes-concurrency package.
|
||||||
-- https://hackage.haskell.org/package/pipes-concurrency-2.0.8/docs/Pipes-Concurrent-Tutorial.html
|
-- https://hackage.haskell.org/package/pipes-concurrency-2.0.8/docs/Pipes-Concurrent-Tutorial.html
|
||||||
|
|
||||||
module Streamly.Examples.AcidRainGame where
|
|
||||||
|
|
||||||
import Streamly
|
import Streamly
|
||||||
import Control.Concurrent (threadDelay)
|
import Control.Concurrent (threadDelay)
|
||||||
import Control.Monad (when)
|
import Control.Monad (when)
|
||||||
@ -38,8 +36,8 @@ game = do
|
|||||||
when (h <= 0) $ fail "You die!"
|
when (h <= 0) $ fail "You die!"
|
||||||
liftIO $ putStrLn $ "Health = " ++ show h
|
liftIO $ putStrLn $ "Health = " ++ show h
|
||||||
|
|
||||||
acidRainGame :: IO ()
|
main :: IO ()
|
||||||
acidRainGame = do
|
main = do
|
||||||
putStrLn "Your health is deteriorating due to acid rain,\
|
putStrLn "Your health is deteriorating due to acid rain,\
|
||||||
\ type \"potion\" or \"quit\""
|
\ type \"potion\" or \"quit\""
|
||||||
_ <- runStateT (runStream game) 60
|
_ <- runStateT (runStream game) 60
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
-- Adapted from the Yampa package.
|
-- Adapted from the Yampa package.
|
||||||
-- Displays a square moving in a circle. To move the position drag the mouse.
|
-- Displays a square moving in a circle. To move the position drag it with the
|
||||||
|
-- mouse.
|
||||||
--
|
--
|
||||||
-- Requires the SDL package, assuming streamly has already been built, you can
|
-- Requires the SDL package, assuming streamly has already been built, you can
|
||||||
-- compile it like this:
|
-- compile it like this:
|
||||||
-- stack ghc --package SDL circle-mouse.hs
|
-- stack ghc --package SDL CirclingSquare.hs
|
||||||
|
|
||||||
module Streamly.Examples.CirclingSquare where
|
|
||||||
|
|
||||||
import Data.IORef
|
import Data.IORef
|
||||||
import Graphics.UI.SDL as SDL
|
import Graphics.UI.SDL as SDL
|
||||||
@ -84,8 +83,8 @@ updateDisplay cref = withClock clock refreshRate displaySquare
|
|||||||
let t = (fromIntegral time) * speed / 1000000
|
let t = (fromIntegral time) * speed / 1000000
|
||||||
in display (x + cos t * radius, y + sin t * radius)
|
in display (x + cos t * radius, y + sin t * radius)
|
||||||
|
|
||||||
circlingSquare :: IO ()
|
main :: IO ()
|
||||||
circlingSquare = do
|
main = do
|
||||||
sdlInit
|
sdlInit
|
||||||
cref <- newIORef (0,0)
|
cref <- newIORef (0,0)
|
||||||
runStream $ once (updateController cref)
|
runStream $ once (updateController cref)
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
module Streamly.Examples.ListDirRecursive where
|
|
||||||
|
|
||||||
import Path.IO (listDir, getCurrentDir)
|
import Path.IO (listDir, getCurrentDir)
|
||||||
import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
|
import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
|
||||||
import Streamly (runStream, coparallely)
|
import Streamly (runStream, coparallely)
|
||||||
import Streamly.Prelude (once)
|
import Streamly.Prelude (once)
|
||||||
|
|
||||||
-- | This example demonstrates that there is little difference between regular
|
-- | List the current directory recursively using concurrent processing
|
||||||
|
--
|
||||||
|
-- This example demonstrates that there is little difference between regular
|
||||||
-- IO code and concurrent streamly code. You can just remove
|
-- IO code and concurrent streamly code. You can just remove
|
||||||
-- 'runStream . coparallely' and this becomes your regular IO code.
|
-- 'runStream . coparallely' and this becomes your regular IO code.
|
||||||
listDirRecursive :: IO ()
|
main :: IO ()
|
||||||
listDirRecursive = do
|
main = do
|
||||||
hSetBuffering stdout LineBuffering
|
hSetBuffering stdout LineBuffering
|
||||||
runStream . coparallely $ getCurrentDir >>= readdir
|
runStream . coparallely $ getCurrentDir >>= readdir
|
||||||
where readdir d = do
|
where readdir d = do
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
|
||||||
module Streamly.Examples.MergeSortedStreams where
|
|
||||||
|
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import System.Random (getStdGen, randoms)
|
import System.Random (getStdGen, randoms)
|
||||||
import Data.List (sort)
|
import Data.List (sort)
|
||||||
@ -36,7 +34,7 @@ merge a b = do
|
|||||||
then (return y) <> merge (return x <> ma) mb
|
then (return y) <> merge (return x <> ma) mb
|
||||||
else (return x) <> merge ma (return y <> mb)
|
else (return x) <> merge ma (return y <> mb)
|
||||||
|
|
||||||
mergeSortedStreams :: IO ()
|
main :: IO ()
|
||||||
mergeSortedStreams = do
|
main = do
|
||||||
xs <- A.toList $ mergeAsync getSorted getSorted
|
xs <- A.toList $ mergeAsync getSorted getSorted
|
||||||
putStrLn $ show $ length xs
|
putStrLn $ show $ length xs
|
||||||
|
@ -1,8 +1,44 @@
|
|||||||
For better examples see the Streamly.Examples module.
|
# Running The Examples
|
||||||
|
|
||||||
|
## Running directly using stack
|
||||||
You can run these examples using `stack` like this:
|
You can run these examples using `stack` like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ stack build
|
$ stack build
|
||||||
$ stack loop.hs
|
$ stack AcidRain.hs
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: This method may not work for `CirclingSquare.hs` SDL animation example.
|
||||||
|
|
||||||
|
## Build and run
|
||||||
|
|
||||||
|
Build the library with the `examples` flag on e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
stack build --flag streamly:examples
|
||||||
|
cabal new-build --flags examples
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run the executables, for example:
|
||||||
|
|
||||||
|
```
|
||||||
|
stack exec AcidRain
|
||||||
|
```
|
||||||
|
|
||||||
|
The executable name are the same as the filenames.
|
||||||
|
|
||||||
|
## Running the SDL animation example
|
||||||
|
|
||||||
|
To include the SDL examples as well build with `examples-sdl` flag:
|
||||||
|
|
||||||
|
```
|
||||||
|
stack build --flag streamly:examples-sdl
|
||||||
|
cabal new-build --flags examples-sdl
|
||||||
|
```
|
||||||
|
|
||||||
|
Make sure that you have the SDL OS package installed on your system and the
|
||||||
|
headers are visible to Haskell build tool.
|
||||||
|
|
||||||
|
```
|
||||||
|
stack exec CirclingSquare
|
||||||
```
|
```
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
module Streamly.Examples.SearchEngineQuery where
|
|
||||||
|
|
||||||
import Streamly
|
import Streamly
|
||||||
import Streamly.Prelude (once)
|
import Streamly.Prelude (once)
|
||||||
import Network.HTTP.Simple
|
import Network.HTTP.Simple
|
||||||
|
|
||||||
-- Runs three search engine queries in parallel.
|
-- | Runs three search engine queries in parallel and prints the search engine
|
||||||
searchEngineQuery :: IO ()
|
-- names in the fastest first order.
|
||||||
searchEngineQuery = do
|
--
|
||||||
putStrLn "Using parallel alternative"
|
-- Does it twice using two different ways.
|
||||||
|
--
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
putStrLn "Using parallel semigroup composition"
|
||||||
runStream . parallely $ google <> bing <> duckduckgo
|
runStream . parallely $ google <> bing <> duckduckgo
|
||||||
|
|
||||||
putStrLn "\nUsing parallel applicative zip"
|
putStrLn "\nUsing parallel applicative zip"
|
||||||
|
159
streamly.cabal
159
streamly.cabal
@ -35,6 +35,7 @@ cabal-version: >= 1.10
|
|||||||
extra-source-files:
|
extra-source-files:
|
||||||
Changelog.md
|
Changelog.md
|
||||||
README.md
|
README.md
|
||||||
|
bench.sh
|
||||||
charts/comparative/AllOperationsataGlance.svg
|
charts/comparative/AllOperationsataGlance.svg
|
||||||
charts/comparative/ComposingPipelineStages.svg
|
charts/comparative/ComposingPipelineStages.svg
|
||||||
stack-7.10.yaml
|
stack-7.10.yaml
|
||||||
@ -59,6 +60,10 @@ flag examples-sdl
|
|||||||
manual: True
|
manual: True
|
||||||
default: False
|
default: False
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Library
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
library
|
library
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
other-modules: Streamly.Core
|
other-modules: Streamly.Core
|
||||||
@ -69,16 +74,6 @@ library
|
|||||||
, Streamly.Tutorial
|
, Streamly.Tutorial
|
||||||
, Streamly
|
, Streamly
|
||||||
|
|
||||||
if flag(examples) || flag(examples-sdl)
|
|
||||||
exposed-modules: Streamly.Examples
|
|
||||||
, Streamly.Examples.SearchEngineQuery
|
|
||||||
, Streamly.Examples.ListDirRecursive
|
|
||||||
, Streamly.Examples.MergeSortedStreams
|
|
||||||
, Streamly.Examples.AcidRainGame
|
|
||||||
|
|
||||||
if flag(examples-sdl)
|
|
||||||
exposed-modules: Streamly.Examples.CirclingSquare
|
|
||||||
|
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
ghc-options: -Wall
|
ghc-options: -Wall
|
||||||
|
|
||||||
@ -95,8 +90,6 @@ library
|
|||||||
-Wredundant-constraints
|
-Wredundant-constraints
|
||||||
-Wnoncanonical-monad-instances
|
-Wnoncanonical-monad-instances
|
||||||
-Wnoncanonical-monadfail-instances
|
-Wnoncanonical-monadfail-instances
|
||||||
if flag(examples-sdl)
|
|
||||||
cpp-options: -DEXAMPLES_SDL
|
|
||||||
|
|
||||||
build-depends: base >= 4.8 && < 5
|
build-depends: base >= 4.8 && < 5
|
||||||
, atomic-primops >= 0.8 && < 0.9
|
, atomic-primops >= 0.8 && < 0.9
|
||||||
@ -114,15 +107,9 @@ library
|
|||||||
build-depends:
|
build-depends:
|
||||||
semigroups >= 0.18 && < 0.19
|
semigroups >= 0.18 && < 0.19
|
||||||
|
|
||||||
if flag(examples) || flag(examples-sdl)
|
-------------------------------------------------------------------------------
|
||||||
build-Depends:
|
-- Test suites
|
||||||
http-conduit >= 2.2.2 && < 2.4
|
-------------------------------------------------------------------------------
|
||||||
, path-io >= 0.1.0 && < 1.4
|
|
||||||
, random >= 1.0.0 && < 1.2
|
|
||||||
|
|
||||||
if flag(examples-sdl)
|
|
||||||
build-Depends:
|
|
||||||
SDL >= 0.6.5 && < 0.7
|
|
||||||
|
|
||||||
test-suite test
|
test-suite test
|
||||||
type: exitcode-stdio-1.0
|
type: exitcode-stdio-1.0
|
||||||
@ -175,6 +162,39 @@ test-suite properties
|
|||||||
, hspec >= 2.0 && < 3
|
, hspec >= 2.0 && < 3
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
test-suite loops
|
||||||
|
type: exitcode-stdio-1.0
|
||||||
|
default-language: Haskell2010
|
||||||
|
main-is: loops.hs
|
||||||
|
hs-source-dirs: test
|
||||||
|
build-Depends:
|
||||||
|
streamly
|
||||||
|
, base >= 4.8 && < 5
|
||||||
|
|
||||||
|
test-suite nested-loops
|
||||||
|
type: exitcode-stdio-1.0
|
||||||
|
default-language: Haskell2010
|
||||||
|
main-is: nested-loops.hs
|
||||||
|
hs-source-dirs: test
|
||||||
|
build-Depends:
|
||||||
|
streamly
|
||||||
|
, base >= 4.8 && < 5
|
||||||
|
, random >= 1.0.0 && < 1.2
|
||||||
|
|
||||||
|
test-suite parallel-loops
|
||||||
|
type: exitcode-stdio-1.0
|
||||||
|
default-language: Haskell2010
|
||||||
|
main-is: parallel-loops.hs
|
||||||
|
hs-source-dirs: test
|
||||||
|
build-Depends:
|
||||||
|
streamly
|
||||||
|
, base >= 4.8 && < 5
|
||||||
|
, random >= 1.0.0 && < 1.2
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Benchmarks
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
benchmark linear
|
benchmark linear
|
||||||
type: exitcode-stdio-1.0
|
type: exitcode-stdio-1.0
|
||||||
hs-source-dirs: benchmark
|
hs-source-dirs: benchmark
|
||||||
@ -229,10 +249,6 @@ benchmark nested
|
|||||||
, random >= 1.0 && < 2.0
|
, random >= 1.0 && < 2.0
|
||||||
, gauge >= 0.2.1 && < 0.3
|
, gauge >= 0.2.1 && < 0.3
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Examples
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
executable chart-linear
|
executable chart-linear
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
hs-source-dirs: benchmark
|
hs-source-dirs: benchmark
|
||||||
@ -259,46 +275,71 @@ executable chart-nested
|
|||||||
else
|
else
|
||||||
buildable: False
|
buildable: False
|
||||||
|
|
||||||
executable loops
|
-------------------------------------------------------------------------------
|
||||||
|
-- Examples
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
executable SearchQuery
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
main-is: loops.hs
|
main-is: SearchQuery.hs
|
||||||
hs-source-dirs: examples
|
hs-source-dirs: examples
|
||||||
if flag(examples) || flag(examples-sdl)
|
if flag(examples) || flag(examples-sdl)
|
||||||
|
buildable: True
|
||||||
|
build-Depends:
|
||||||
|
streamly
|
||||||
|
, base >= 4.8 && < 5
|
||||||
|
, http-conduit >= 2.2.2 && < 2.4
|
||||||
|
else
|
||||||
|
buildable: False
|
||||||
|
|
||||||
|
executable ListDir
|
||||||
|
default-language: Haskell2010
|
||||||
|
main-is: ListDir.hs
|
||||||
|
hs-source-dirs: examples
|
||||||
|
if flag(examples) || flag(examples-sdl)
|
||||||
|
buildable: True
|
||||||
|
build-Depends:
|
||||||
|
streamly
|
||||||
|
, base >= 4.8 && < 5
|
||||||
|
, path-io >= 0.1.0 && < 1.4
|
||||||
|
else
|
||||||
|
buildable: False
|
||||||
|
|
||||||
|
executable MergeSort
|
||||||
|
default-language: Haskell2010
|
||||||
|
main-is: MergeSort.hs
|
||||||
|
hs-source-dirs: examples
|
||||||
|
if flag(examples) || flag(examples-sdl)
|
||||||
|
buildable: True
|
||||||
|
build-Depends:
|
||||||
|
streamly
|
||||||
|
, base >= 4.8 && < 5
|
||||||
|
, random >= 1.0.0 && < 1.2
|
||||||
|
else
|
||||||
|
buildable: False
|
||||||
|
|
||||||
|
executable AcidRain
|
||||||
|
default-language: Haskell2010
|
||||||
|
main-is: AcidRain.hs
|
||||||
|
hs-source-dirs: examples
|
||||||
|
if flag(examples) || flag(examples-sdl)
|
||||||
|
buildable: True
|
||||||
|
build-Depends:
|
||||||
|
streamly
|
||||||
|
, base >= 4.8 && < 5
|
||||||
|
, mtl >= 2.2 && < 3
|
||||||
|
else
|
||||||
|
buildable: False
|
||||||
|
|
||||||
|
executable CirclingSquare
|
||||||
|
default-language: Haskell2010
|
||||||
|
main-is: CirclingSquare.hs
|
||||||
|
hs-source-dirs: examples
|
||||||
|
if flag(examples-sdl)
|
||||||
buildable: True
|
buildable: True
|
||||||
build-Depends:
|
build-Depends:
|
||||||
streamly
|
streamly
|
||||||
, base >= 4.8 && < 5
|
, base >= 4.8 && < 5
|
||||||
else
|
, SDL >= 0.6.5 && < 0.7
|
||||||
buildable: False
|
|
||||||
|
|
||||||
executable nested-loops
|
|
||||||
default-language: Haskell2010
|
|
||||||
main-is: nested-loops.hs
|
|
||||||
hs-source-dirs: examples
|
|
||||||
if flag(examples) || flag(examples-sdl)
|
|
||||||
buildable: True
|
|
||||||
build-Depends:
|
|
||||||
streamly
|
|
||||||
, base >= 4.8 && < 5
|
|
||||||
, random >= 1.0.0 && < 1.2
|
|
||||||
if impl(ghc < 8.0)
|
|
||||||
build-depends:
|
|
||||||
transformers >= 0.4 && < 0.6
|
|
||||||
else
|
|
||||||
buildable: False
|
|
||||||
|
|
||||||
executable parallel-loops
|
|
||||||
default-language: Haskell2010
|
|
||||||
main-is: parallel-loops.hs
|
|
||||||
hs-source-dirs: examples
|
|
||||||
if flag(examples) || flag(examples-sdl)
|
|
||||||
buildable: True
|
|
||||||
build-Depends:
|
|
||||||
streamly
|
|
||||||
, base >= 4.8 && < 5
|
|
||||||
, random >= 1.0.0 && < 1.2
|
|
||||||
if impl(ghc < 8.0)
|
|
||||||
build-depends:
|
|
||||||
transformers >= 0.4 && < 0.6
|
|
||||||
else
|
else
|
||||||
buildable: False
|
buildable: False
|
||||||
|
@ -41,10 +41,6 @@ main = do
|
|||||||
-- Serial (single-threaded) stream generator loops
|
-- 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
|
-- Generates a value and then loops. Can be used to generate an infinite
|
||||||
-- stream. Interleaves the generator and the consumer.
|
-- stream. Interleaves the generator and the consumer.
|
||||||
loopTail :: Int -> Stream Int
|
loopTail :: Int -> Stream Int
|
||||||
@ -64,11 +60,6 @@ main = do
|
|||||||
-- Concurrent (multi-threaded) adaptive demand-based stream generator loops
|
-- 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 -> Stream Int
|
loopTailA :: Int -> Stream Int
|
||||||
loopTailA x = do
|
loopTailA x = do
|
||||||
once $ putStrLn "LoopTailA..."
|
once $ putStrLn "LoopTailA..."
|
||||||
@ -82,8 +73,3 @@ main = do
|
|||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- Parallel (fairly scheduled, multi-threaded) stream generator loops
|
-- 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.
|
|
||||||
|
@ -14,6 +14,8 @@ main = runStream $ do
|
|||||||
|
|
||||||
where
|
where
|
||||||
|
|
||||||
|
-- we can just use
|
||||||
|
-- parallely $ mconcat $ replicate n $ once (...)
|
||||||
loop :: String -> Int -> StreamT IO String
|
loop :: String -> Int -> StreamT IO String
|
||||||
loop name n = do
|
loop name n = do
|
||||||
rnd <- once (randomIO :: IO Int)
|
rnd <- once (randomIO :: IO Int)
|
||||||
|
@ -2,19 +2,25 @@ import Control.Concurrent (myThreadId, threadDelay)
|
|||||||
import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
|
import System.IO (stdout, hSetBuffering, BufferMode(LineBuffering))
|
||||||
import System.Random (randomIO)
|
import System.Random (randomIO)
|
||||||
import Streamly
|
import Streamly
|
||||||
import Streamly.Prelude (once)
|
import qualified Streamly.Prelude as S
|
||||||
|
|
||||||
main = runStream $ do
|
main = do
|
||||||
once $ hSetBuffering stdout LineBuffering
|
hSetBuffering stdout LineBuffering
|
||||||
x <- loop "A" `parallel` loop "B"
|
runStream $ do
|
||||||
once $ myThreadId >>= putStr . show
|
x <- S.take 10 $ loop "A" `parallel` loop "B"
|
||||||
>> putStr " "
|
S.once $ myThreadId >>= putStr . show
|
||||||
>> print x
|
>> putStr " got "
|
||||||
|
>> print x
|
||||||
|
|
||||||
where
|
where
|
||||||
|
|
||||||
|
-- we can just use
|
||||||
|
-- parallely $ cycle1 $ once (...)
|
||||||
loop :: String -> Stream (String, Int)
|
loop :: String -> Stream (String, Int)
|
||||||
loop name = do
|
loop name = do
|
||||||
once $ threadDelay 1000000
|
S.once $ threadDelay 1000000
|
||||||
rnd <- once (randomIO :: IO Int)
|
rnd <- S.once (randomIO :: IO Int)
|
||||||
|
S.once $ myThreadId >>= putStr . show
|
||||||
|
>> putStr " yielding "
|
||||||
|
>> print rnd
|
||||||
return (name, rnd) `parallel` loop name
|
return (name, rnd) `parallel` loop name
|
||||||
|
Loading…
Reference in New Issue
Block a user