Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 13 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,20 @@ 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`, `MonadError`, and
`Applicative`, `Bind`, `Monad`, `Alt`, `Plus`, `MonadEffect`, `MonadError`, and
`Parallel`. These instances allow you to compose asynchronous code as easily
as `Eff`, as well as interop with existing `Eff` code.
as `Effect`, as well as interop with existing `Effect` 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 you can make an `Aff` from
low-level `Eff` callbacks with `makeAff`.
low-level `Effect` callbacks with `makeAff`.

```purescript
makeAff :: forall eff a. ((Either Error a -> Eff eff Unit) -> Eff eff (Canceler eff)) -> Aff eff a
makeAff :: forall a. ((Either Error a -> Effect Unit) -> Effect Canceler) -> Aff a
```

This function expects you to provide a handler, which should call the
Expand All @@ -60,7 +60,7 @@ 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.

`Control.Monad.Aff.Compat` provides functions for easily binding FFI
`Effect.Aff.Compat` provides functions for easily binding FFI
definitions:

```javascript
Expand All @@ -84,14 +84,14 @@ exports._ajaxGet = function (request) { // accepts a request
```

```purescript
foreign import _ajaxGet :: forall eff. Request -> EffFnAff (ajax :: AJAX | eff) Response
foreign import _ajaxGet :: Request -> EffectFnAff Response
```

We can wrap this into an asynchronous computation like so:

```purescript
ajaxGet :: forall eff. Request -> Aff (ajax :: AJAX | eff) Response
ajaxGet = fromEffFnAff <<< _ajaxGet
ajaxGet :: Request -> Aff Response
ajaxGet = fromEffectFnAff <<< _ajaxGet
```

This eliminates callback hell and allows us to write code simply using `do`
Expand All @@ -103,22 +103,18 @@ example = do
log response.body
```

## Eff
## Effect

All purely synchronous computations (`Eff`) can be lifted to asynchronous
computations with `liftEff` defined in `Control.Monad.Eff.Class`.
All purely synchronous computations (`Effect`) can be lifted to asynchronous
computations with `liftEffect` defined in `Effect.Class`.

```purescript
liftEff $ log "Hello world!"
liftEffect $ log "Hello world!"
```

This lets you write your whole program in `Aff`, and still call out to
synchronous code.

If your `Eff` code throws exceptions (`exception :: EXCEPTION`), you can
remove the exception label using `liftEff'`. Exceptions are part of `Aff`s
built-in semantics, so they will always be caught and propagated anyway.

## Dealing with Failure

`Aff` has error handling baked in, so ordinarily you don't have to worry
Expand Down Expand Up @@ -188,7 +184,7 @@ Because Javascript is single-threaded, forking does not actually cause the
computation to be run in a separate thread. Forking just allows the subsequent
actions to execute without waiting for the forked computation to complete.

Forking returns a `Fiber eff a`, representing the deferred computation. You can
Forking returns a `Fiber a`, representing the deferred computation. You can
kill a `Fiber` with `killFiber`, which will run any cancelers and cleanup, and
you can observe a `Fiber`'s final value with `joinFiber`. If a `Fiber` threw
an exception, it will be rethrown upon joining.
Expand All @@ -203,53 +199,6 @@ example = do
else (log "Not Canceled")
```


## AVars

The `Control.Monad.Aff.AVar` module contains asynchronous variables, which
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 `putVar`.

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

Likewise, calling `putVar` on a filled `AVar` will queue until it is emptied by
a `takeVar`.

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

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

## Parallel Execution

The `Parallel` instance for `Aff` makes writing parallel computations a breeze.
Expand Down
27 changes: 12 additions & 15 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,19 @@
"package.json"
],
"dependencies": {
"purescript-console": "^3.0.0",
"purescript-exceptions": "^3.0.0",
"purescript-functions": "^3.0.0",
"purescript-parallel": "^3.0.0",
"purescript-transformers": "^3.0.0",
"purescript-unsafe-coerce": "^3.0.0",
"purescript-datetime": "^3.0.0",
"purescript-free": "^4.0.1",
"purescript-st": "^3.0.0",
"purescript-type-equality": "^2.1.0",
"purescript-avar": "^2.0.0"
"purescript-exceptions": "#compiler/0.12",
"purescript-functions": "#compiler/0.12",
"purescript-parallel": "#compiler/0.12",
"purescript-transformers": "#compiler/0.12",
"purescript-unsafe-coerce": "#compiler/0.12",
"purescript-datetime": "#compiler/0.12",
"purescript-effect": "#compiler/0.12"
},
"devDependencies": {
"purescript-partial": "^1.2.0",
"purescript-minibench": "^1.0.0",
"purescript-assert": "^3.0.0",
"purescript-js-timers": "^3.0.0"
"purescript-console": "#compiler/0.12",
"purescript-partial": "#compiler/0.12",
"purescript-minibench": "#compiler/0.12",
"purescript-assert": "#compiler/0.12",
"purescript-free": "#compiler/0.12"
}
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
"devDependencies": {
"jscs": "^3.0.7",
"jshint": "^2.9.4",
"pulp": "^11.0.0",
"pulp": "^12.0.0",
"purescript-psa": "^0.5.0",
"purescript": "^0.11.0",
"purescript": "^0.12.0-rc1",
"rimraf": "^2.5.4"
},
"jscsConfig": {
Expand Down
Loading