@natefaubion natefaubion released this Aug 24, 2018 · 3 commits to master since this release

Assets 2
  • Don't resume from an enqueued task if interrupted (#162)
  • Fix finalization after failure (#161)

@natefaubion natefaubion released this Jul 12, 2018 · 5 commits to master since this release

Assets 2
  • Fixes runtime error when running an async canceler in a ParAff apply operation (#153)

@garyb garyb released this May 25, 2018 · 6 commits to master since this release

Assets 2

Updated for PureScript 0.12

@natefaubion natefaubion released this Apr 18, 2018 · 9 commits to master since this release

Assets 2
  • Fixes bhead is not a function FFI errors when yielding a fork at the tail of a fresh attempt context (possibly through bracket acquisition or catchError).

@natefaubion natefaubion released this Apr 6, 2018 · 10 commits to master since this release

Assets 2

@natefaubion natefaubion released this Jan 14, 2018 · 12 commits to master since this release

Assets 2
  • Fix regression in ParAff Applicative behavior when an exception occurs.

@natefaubion natefaubion released this Nov 19, 2017 · 13 commits to master since this release

Assets 2
  • Fixes JavaScript runtime error in ParAff cancellation.

@natefaubion natefaubion released this Sep 14, 2017 · 15 commits to master since this release

Assets 2

This release (v4.0.0) features a revamped API for writing more expressive asynchronous programs with stronger guarantees.

  • Fiber cooperative multi-tasking primitive for fork/join workflows.
  • Stronger cleanup guarantees with bracket and supervise.
  • Reformulated AVar semantics
  • Rewritten core with an emphasis on performance and consistency.

New Features and Enhancements


Previously, Affs supported forkAff, but it was very difficult to get values back when forked computations completed. Libraries like purescript-aff-future were written to overcome this limitation (though with limitations of their own). The semantics of purescript-aff-future have been assimilated into Aff through the Fiber type without any of the previous limitaions (like lack of cancellation). Fibers make it easy to not only fork computations, but also share their results among many consumers with joinFiber, which will wait until the Fiber completes, or yield immediately if it has already resolved. If a Fiber threw an exception, then the exception will be rethrown in the observer. Fibers additionally support cancellation (killFiber) and finalizers for cleanup (bracket).


When we kill/cancel a Fiber, often times we need to make sure some resource gets released. bracket lets you take control of the acquire/use/release resource cycle.

example =
    (openFile myFile) -- Acquire a resource
    (\file -> closeFile file) -- Release the resource
    (\file -> appendFile "hello" file) -- Use the resource

In the example above, the runtime will always ensure the "release" effect will run even in the presence of cancellation. There is also generalBracket, which lets you observe whether the primary action completed successfully, threw an exception, or was killed asynchronously and run different cleanup effects accordingly.


Sometimes we need to fork many Fibers for a task, but it's possible (often through cancellation) for these sub-tasks to leak. We've introduced a supervise combinator which will automatically keep track of forked Fibers and clean them up and run their finalizers once the computation completes or is cancelled.

example = supervise do
  _ <- forkAff requestA
  _ <- forkAff requestB

In the above example, if requestA or requestB are still running when requestC completes, they will be killed by the runtime and have their finalizers run.


As an alternative to forkAff, which eagerly forks and runs a computations, we've introduced suspendAff. This forks a computation but does not initiate it until a result is demanded via joinFiber. Results are still memoized (as all Fiber results are), but are just computed lazily.


With the old callback approach, each bind resulted in more and more stack, and it was trivial to blow the stack unless you explicitly used tailRecM. The Aff interpreter now uses a constant amount of stack space, making tailRecM unnecesary. This extends to ParAff as well.

Uncaught exceptions

Previously, exceptions thrown in forked computations were completely swallowed. This made it extremely difficult to diagnose bugs. Now if a Fiber has no observers and it throws an exception, the exception will always be rethrown in a fresh stack. This can be observed by things like window.onerror or just by watching the console.

Breaking Changes

  • The low-level callback representation is no longer relevant. If you've defined Aff effects via the FFI, you should transition to using Control.Monad.Aff.Compat, which provides an EffFn adapter. This makes it easy to use idiomatic JavaScript callbacks when building Aff actions.
  • The AVar API methods have changed to match Haskell's MVar API. putVar now blocks until the AVar actually assimilates the value. Previously, putVar would queue the value, but yield immediately. It's possible to recover similar behavior as the old API with forkAff (try (putVar value avar)) (though this should be considered mildly unsafe), or you can use tryPutVar which will attempt a synchronous put.
  • Argument order for AVar and Fiber operations consistently put the subject last.
  • Several unlawful instances where removed for Aff (Alternative, MonadPlus, and MonadZero).
  • forkAff now returns a Fiber rather than a Canceler.
  • forkAll was removed. Just use Traversable and forkAff directly.
  • cancel was removed. Use killFiber.
  • The signature of makeAff has changed to provide a single callback which takes an Either Error a argument. Cancelers are also required. If you are sure you have no means of cancelling an action, you can use nonCanceler or mempty.
  • Cancelers no longer yield Boolean. This was meaningless and not useful, so all cancellation effects now yield Unit.
  • ParAff is no longer a newtype. Parallel computations should be constructed via Control.Parallel with parallel and sequential.

@natefaubion natefaubion released this Sep 12, 2017 · 16 commits to master since this release

Assets 2
  • Rename atomically to invincible.
  • Killing a suspended fiber should be synchronous.