@@ -103,19 +103,47 @@ function:
106+There are two ways to achieve the race functionality, using `take` or using
109+#### `race` Using `take`
106−To run multiple actions and use the first result:
111+We can run multiple actions concurrently and take the first result that
108```haskell
114```haskell
109 urls <- S.toList $ S.take 1 $ parallely $ getURL 1 |: getURL 2 |: S.nil
115 urls <- S.toList $ S.take 1 $ parallely $ getURL 1 |: getURL 2 |: S.nil
112After the first result arrives, the rest of the actions are canceled
118After the first result arrives, the rest of the actions are canceled
113−automatically. You can take first `n` results as they arrive:
119+automatically. In general, we can take first `n` results as they arrive:
115```haskell
121```haskell
116 urls <- S.toList $ S.take 2 $ parallely $ getURL 1 |: getURL 2 |: S.nil
122 urls <- S.toList $ S.take 2 $ parallely $ getURL 1 |: getURL 2 |: S.nil
125+#### `race` Using Exceptions
127+When an exception occurs in a concurrent stream all the concurrently running
128+actions are cacnceled on arrival of the exception. This can be used to
129+implement the race functionality. Each action in the stream can use an
130+exception to communicate the result. As soon as the first result arrives all
131+other actions will be canceled, for example:
134+ data Result = Result String deriving Show
135+ instance Exception Result
138+ url <- try $ runStream $ parallely $
139+ (getURL 2 >>= throwM . Result)
140+ |: (getURL 1 >>= throwM . Result)
143+ Left (e :: SomeException) -> print e
144+ Right _ -> undefined
119### mapConcurrently
147### mapConcurrently
121There are many ways to map concurrently on a container and collect the results:
149There are many ways to map concurrently on a container and collect the results: