1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
|
## say
Send textual messages to a `Handle` in a thread-friendly way.
[](https://travis-ci.org/fpco/say) [](https://ci.appveyor.com/project/snoyberg/say)
The motivation for this package is described in [a blog post on Haskell's
Missing Concurrency
Basics](http://www.snoyman.com/blog/2016/11/haskells-missing-concurrency-basics).
The simple explanation is, when writing a line of textual data to a `Handle` -
such as sending some messages t o ther terminal - we'd like to have the
following properties:
* Properly handle character encoding settings on the `Handle`
* For reasonably sized messages, ensure that the entire message is written in
one chunk to avoid interleaving data with other threads
* This includes the trailing newline character
* Avoid unnecessary memory allocations and copies
* Minimize locking
* Provide a simple API
On the last point: for the most part, you can make the following substitutions
in your API usage:
* Replace `putStrLn` with `say`
* Replace `print` with `sayShow`
* If you're using a `String` instead of `Text`, replace `putStrLn` with `sayString`
In addition, `sayErr`, `sayErrString` and `sayErrShow` work on
standard error instead, and `hSay`, `hSayString` and `hSayShow` work
on arbitrary `Handle`s.
```haskell
#!/usr/bin/env stack
-- stack --install-ghc --resolver lts-6.23 runghc --package async --package say
import Control.Concurrent.Async (mapConcurrently)
import Control.Monad (forM_, void)
import Say (sayString)
worker :: Int -> IO ()
worker ident = forM_ [1..1000] $ \msg -> sayString $ concat
[ "Hello, I am worker #"
, show ident
, ", and this is message #"
, show msg
]
main :: IO ()
main = void $ mapConcurrently worker [1..100]
```
|