1{-# OPTIONS_GHC -fno-warn-unused-imports #-}
3-- Module : ReactiveProgramming
4-- Copyright : (c) 2017 Composewell Technologies
7-- Maintainer : streamly@composewell.com
9-- In this tutorial we will show how Streamly can be used for reactive
10-- programming. Before you go through this tutorial we recommend that you take
11-- a look at the Streamly concurrent programming tutorial.
13module ReactiveProgramming
15 -- * Reactive Programming
18 -- * Where to go next?
23import Streamly.Prelude
25import Control.Applicative
27import Control.Monad.IO.Class (MonadIO(..))
28import Control.Monad.Trans.Class (MonadTrans (lift))
32-- Reactive programming is nothing but concurrent streaming which is what
33-- streamly is all about. With streamly we can generate streams of events,
34-- merge streams that are generated concurrently and process events
35-- concurrently. We can do all this without any knowledge about the specifics
36-- of the implementation of concurrency. In the following example you will see
37-- that the code is just regular Haskell code without much streamly APIs used
38-- (active hyperlinks are the streamly APIs) and yet it is a reactive
41-- This application has two independent and concurrent sources of event
42-- streams, @acidRain@ and @userAction@. @acidRain@ continuously generates
43-- events that deteriorate the health of the character in the game.
44-- @userAction@ can be "potion" or "quit". When the user types "potion" the
45-- health improves and the game continues.
48-- {-\# LANGUAGE FlexibleContexts \#-}
50-- import "Streamly.Prelude" (MonadAsync, SerialT)
51-- import "Streamly.Prelude" as Stream
52-- import Control.Monad (void)
53-- import Control.Monad.IO.Class (MonadIO(liftIO))
54-- import Control.Monad.State (MonadState, get, modify, runStateT)
56-- data Event = Quit | Harm Int | Heal Int deriving (Show)
58-- userAction :: MonadAsync m => 'SerialT' m Event
59-- userAction = Stream.'repeatM' $ liftIO askUser
64-- "potion" -> return (Heal 10)
65-- "harm" -> return (Harm 10)
66-- "quit" -> return Quit
67-- _ -> putStrLn "Type potion or harm or quit" >> askUser
69-- acidRain :: MonadAsync m => 'SerialT' m Event
70-- acidRain = Stream.'fromAsync' $ Stream.'constRate' 1 $ Stream.'repeatM' $ liftIO $ return $ Harm 1
72-- data Result = Check | Done
74-- runEvents :: (MonadAsync m, MonadState Int m) => 'SerialT' m Result
76-- event \<- userAction \`Stream.'parallel'` acidRain
78-- Harm n -> modify (\\h -> h - n) >> return Check
79-- Heal n -> modify (\\h -> h + n) >> return Check
82-- data Status = Alive | GameOver deriving Eq
84-- getStatus :: (MonadAsync m, MonadState Int m) => Result -> m Status
87-- Done -> liftIO $ putStrLn "You quit!" >> return GameOver
90-- liftIO $ if (h <= 0)
91-- then putStrLn "You die!" >> return GameOver
92-- else putStrLn ("Health = " <> show h) >> return Alive
96-- putStrLn "Your health is deteriorating due to acid rain, type \\\"potion\\\" or \\\"quit\\\""
97-- let runGame = Stream.'drainWhile' (== Alive) $ Stream.'mapM' getStatus runEvents
98-- void $ runStateT runGame 60
101-- You can also find the source of this example in the streamly-examples repo
102-- as <https://github.com/composewell/streamly-examples/tree/master/AcidRain.hs AcidRain.hs>.
103-- It has been adapted from Gabriel's
104-- <https://hackage.haskell.org/package/pipes-concurrency-2.0.8/docs/Pipes-Concurrent-Tutorial.html pipes-concurrency>
106-- This is much simpler compared to the pipes version because of the builtin
107-- concurrency in streamly. You can also find a SDL based reactive programming
108-- example adapted from Yampa in
109-- <https://github.com/composewell/streamly-examples/tree/master/CirclingSquare.hs CirclingSquare.hs>.
113-- Streamly is highly optimized for performance, it is designed for serious
114-- high performing, concurrent and scalable applications. We have created the
115-- <https://hackage.haskell.org/package/streaming-benchmarks streaming-benchmarks>
116-- package which is specifically and carefully designed to measure the
117-- performance of Haskell streaming libraries fairly and squarely in the right
118-- way. Streamly performs at par or even better than most streaming libraries
119-- for serial operations even though it needs to deal with the concurrency
124-- * See the examples in <https://github.com/composewell/streamly-examples streamly-examples> repo.
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list