Skip to content

Commit

Permalink
README edits
Browse files Browse the repository at this point in the history
  • Loading branch information
natefaubion committed Aug 18, 2017
1 parent 7576856 commit 69bf7ed
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 20 deletions.
64 changes: 45 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ asynchronously without any callbacks. Error handling is baked in so you only
deal with it when you want to.

The library contains instances for `Semigroup`, `Monoid`, `Apply`,
`Applicative`, `Bind`, `Monad`, `Alt`, `Plus`, `MonadEff`, and `MonadError`.
These instances allow you to compose asynchronous code as easily as `Eff`, as
well as interop with existing `Eff` code.
`Applicative`, `Bind`, `Monad`, `Alt`, `Plus`, `MonadEff`, `MonadError`, and
`Parallel`. These instances allow you to compose asynchronous code as easily
as `Eff`, as well as interop with existing `Eff` code.

## Escaping Callback Hell

Hopefully, you're using libraries that already use the `Aff` type, so you
don't even have to think about callbacks!

If you're building your own library, then *purescript-aff* provides a
`makeAff` function:
If you're building your own library, then you can make an `Aff` from
low-level `Eff` callbacks with `makeAff`.

```purescript
makeAff :: forall eff a. ((Either Error a -> Eff eff Unit) -> Eff eff (Canceler eff)) -> Aff eff a
Expand All @@ -60,8 +60,8 @@ You should also return `Canceler`, which is just a cleanup effect. Since
`Aff` threads may be killed, all asynchronous operations should provide a
mechanism for unscheduling it.

*purescript-aff* also provides functions for easily binding FFI definitions in
`Control.Monad.Aff.Compat`.
`Control.Monad.Aff.Compat` provides functions for easily binding FFI
definitions:

```javascript
exports._ajaxGet = function (request) { // accepts a request
Expand Down Expand Up @@ -108,12 +108,9 @@ example = do
## Eff

All purely synchronous computations (`Eff`) can be lifted to asynchronous
computations with `liftEff` defined in `Control.Monad.Eff.Class` (see
[here](https://github.com/purescript/purescript-eff)).
computations with `liftEff` defined in `Control.Monad.Eff.Class`.

```purescript
import Control.Monad.Eff.Class
liftEff $ log "Hello world!"
```

Expand Down Expand Up @@ -212,18 +209,47 @@ example = do
## AVars

The `Control.Monad.Aff.AVar` module contains asynchronous variables, which
are very similar to Haskell's `MVar`. These can be used as low-level building
blocks for asynchronous programs.
are very similar to Haskell's `MVar`.

`AVar`s represent a value that is either full or empty. Calling `takeVar` on
an empty `AVar` will queue until it is filled by a matching `putVar`.

```purescript
example = d
v <- makeEmptyVar
example = do
var <- makeEmptyVar
_ <- forkAff do
value <- takeVar var
log $ "Got a value: " <> value
_ <- forkAff do
delay (Milliseconds 50.0)
putVar v 1.0
a <- takeVar v
log ("Succeeded with " <> show a)
delay (Milliseconds 100.0)
putVar var "hello"
pure unit
```
```
(Waits 100ms)
> Got a value: hello
```

Likewise, calling `putVar` will queue until it is taken:

```purescript
example = do
var <- makeEmptyVar
_ <- forkAff do
delay (Milliseconds 100.0)
value <- takeVar var
log $ "Got a value: " <> value
putVar var "hello"
log "Value taken"
```
```
(Waits 100ms)
> Value taken
> Got a value: hello
```

These combinators (and a few more) can be used as the building blocks for
complex asynchronous coordination.

## Parallel Execution

Expand Down
17 changes: 16 additions & 1 deletion test/Test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Prelude

import Control.Alt ((<|>))
import Control.Monad.Aff (Aff, Canceler(..), runAff_, launchAff, makeAff, try, bracket, generalBracket, delay, forkAff, suspendAff, joinFiber, killFiber, never, supervise)
import Control.Monad.Aff.AVar (AVAR, makeEmptyVar, takeVar, putVar)
import Control.Monad.Eff (Eff, runPure)
import Control.Monad.Eff.Class (class MonadEff, liftEff)
import Control.Monad.Eff.Console (CONSOLE)
Expand All @@ -24,7 +25,7 @@ import Data.Time.Duration (Milliseconds(..))
import Data.Traversable (traverse)
import Test.Assert (assert', ASSERT)

type TestEffects eff = (assertASSERT, consoleCONSOLE, refREF, exceptionEXCEPTION | eff)
type TestEffects eff = (assertASSERT, consoleCONSOLE, refREF, exceptionEXCEPTION, avarAVAR | eff)
type TestEff eff = Eff (TestEffects eff)
type TestAff eff = Aff (TestEffects eff)

Expand Down Expand Up @@ -514,6 +515,19 @@ test_fiber_apply = assert "fiber/apply" do
n ← readRef ref
pure (a == 22 && b == 22 && n == 1)

test_avar_order eff. TestAff eff Unit
test_avar_order = assert "avar/order" do
ref ← newRef ""
var ← makeEmptyVar
f1 ← forkAff do
delay (Milliseconds 10.0)
value ← takeVar var
modifyRef ref (_ <> value)
putVar var "foo"
modifyRef ref (_ <> "taken")
joinFiber f1
eq "takenfoo" <$> readRef ref

test_parallel_stack eff. TestAff eff Unit
test_parallel_stack = assert "parallel/stack" do
ref ← newRef 0
Expand Down Expand Up @@ -558,6 +572,7 @@ main = do
test_parallel_alt_sync
test_parallel_mixed
test_kill_parallel_alt
test_avar_order
test_fiber_map
test_fiber_apply
-- Turn on if we decide to schedule forks
Expand Down

0 comments on commit 69bf7ed

Please sign in to comment.