Release notes

Folktale v2.0.0 is the result of more than one year of work in constructing and documenting a coherent basis for functional programming in JavaScript. There’s a lot left to be done, but this release is an important step in that direction.

This document describes the most noteworthy changes, see the full changelog for all the changes.

Contents

Highlights

  • Moving away from currying — this release prefers leveraging native JavaScript constructs instead of currying, which does not compose well with most JavaScript (variadic) APIs.

  • Simplified Union types — the new adt/union module allows constructing union types in an easy way.

  • A more robust Task API — the new Task API includes resource handling at the core of its model, and tries to mitigate the possibility of race conditions as much as possible.

Moving away from currying

Folktale 1 relied heavily on currying. This caused problems when interacting with native JavaScript functions. The new library aims to interact better with JavaScript, so native JavaScript constructs are preferred.

Some functions in the new Folktale library are still curried by default. compose is a good example. It takes two functions, and returns a new one that takes an argument. The major difference is that there’s no automatic unrolling happening.

// Folktale 1.x
const compose = curry(3, (f, g, x) => ...);

compose(f, g, x, y) === compose(f)(g)(x)(y);
compose(f, g, x)    === compose(f)(g)(x);
compose(f, g)(x)    === compose(f)(g)(x);
compose(f)(g)(x)    === compose(f)(g)(x);


// Folktale 2.x+
const compose = (f, g) => (x) => ...;

compose(f, g, x, y) === compose(f, g);
compose(f, g, x)    === compose(f, g);
compose(f, g)(x)    === compose(f, g)(x);
compose(f)(g)(x)    === compose(f)(g)(x); // an error

More details on currying can be seen in the curry() documentation.

Simplified Union types

JavaScript does not have native support for tagged unions. This is one of the core features of functional programming. Unions help programmers model possibilities, and often help defining recursive procedures.

Folktale 2 helps with this by providing a new union module. This module allows creating union types by listing the possibilities and their fields.

const { union } = require('folktale/adt/union');

const List = union('List', {
  Empty(){ },

  Cons(value, rest) {
    return { value, rest };
  }
});

The union module also provides default features for these data structures. The derivation feature allows users to share extensions to these defaults. More details on this module can be found in the union documentation.

A more robust Task API

Folktale 1 introduced a concept of Tasks to help with asynchronous computations. However, the API made composition difficult, and increased the likelihood of hitting race conditions and other edge cases.

Folktale 2 includes a full redesign of the Task API, focused on ease of use, compositionality and robustness. Thew new Task model now fully supports asynchronous resource lifecycle handling, concurrent composition, and task cancellation.

The Task documentation describes this in details.

Acknowledgements

A huge thank you to everyone who contributed to improving Folktale, by reporting errors, sending feedback, talking about it, sending patches, etc.

A special thank you to: