Overview
Folktale is a library to support a functional style of programming in JavaScript. In its current version Folktale provides utilities for combining functions, transforming objects, modelling data, handling errors, and concurrency.
The API reference provides detailed documentation on these, but may be difficult to navigate. This page serves as an introduction to the most important concepts.
Contents
- Folktale and Functional Programming
- Programming with functions
- Handling errors
- Modelling data
- Concurrency
Folktale and Functional Programming
The goal of Folktale is to be a fully-featured standard library that supports a functional style of programming in JavaScript and TypeScript. In this style, functionality is broken down in small and focused functions, and more complex functionality is created by combining these functions. Functional Programming makes these pieces easier to combine by avoiding accidental complexities, such as overloading polymorphism and side-effects.
Other characteristics from the functional style of programming are stricter definitions of data structures to simplify transforming them and aid correctness; and the use of pure structures. That is, instead of changing a structure in memory, an entire new structure is created for every change.
To do this efficiently, one needs special implementations of data structures, and new ways to construct them. Folktale’s goals is to help you achieve this.
Programming with functions
Core to functional programming is the idea of programming with functions (in the more mathematical sense of the word). The concept is fairly broad, and most of the things encompassed by it can be achieved with some work in ECMAScript.
For example, sometimes it’s important to evaluate an expression eagerly when using higher-order
functions (such as Array.map
), because otherwise the expression could be evaluated more than
once. This happens in particular where side-effects are concerned:
In order to evaluate it only once, we’d need to evaluate the expression and store its value in some variable:
Another option is using a functional combinator like constant:
Folktale’s core/lambda
module tries to provide
these small utilities that help combining and transforming functions in a program. See the
module’s documentation for more details.
Handling errors
There are a few ways in which errors are generally handled in JavaScript, but they tend to
boil down mostly to control-flow structures (if/else
) or exceptions (try/catch
). These
tend to either be hard to predict or hard to maintain. Folktale provides three data
structures to help with error handling:
- Maybe - A structure that helps handling values
that may or may not be present. For example, a function like
Array.find
may or may not be able to return a value. People tend to usenull
as a return value when the function fails to return one, but that’s ambiguous if the original array had anull
value. Maybe allows one to deal with these cases without ambiguity, and forces errors to be handled.
- Result - A structure that models the result of functions that may fail. For example, parsing a JSON string into native objects doesn’t always succeed, but it may fail for different reasons: the JSON string could be malformed, the reifying function could throw an error, etc. Ideally we’d capture this additional information so the person receiving the result of the parsing could deal with the failure in an appropriate manner. Result lets you do this safely.
- Validation - A structure that helps with validations (such as form validations). A validation function may succeed or fail, like the functions mentioned above, but unlike the cases where Result is indicated, when doing validations one generally wants to capture all of the failures and display them back to the user. Validation works similarly to Result, but provides methods that help aggregating all failures, rather than stopping at the first one.
Modelling data
Another core part of functional programming is modelling data. Properly modelling what you can and can’t do with a data structure helps writing correct programs, but JavaScript has very few tools for this. Folktale lessens this by adding experimental support for tagged unions, which are used to model possibilities in a particular type of data.
Think of tagged unions as a beefed-up enum structure. For example, a binary tree can be seen as a type with the possibilities: “a branch node” or “a leaf node”:
Folktale allows you to use a limited form of pattern matching to operate on these structures:
More documentation can be found in the adt/union
module reference.
Concurrency
JavaScript has added better support to concurrency recently with Promises and async/await
,
but Promises work at the value level, so they can’t help with actions and their composition.
For example, if one sends an HTTP request, they may want to cancel it if it takes too long,
or they may send two HTTP requests, take the first that returns, and cancel the other one.
None of this is supported by Promises, but they’re supported by Folktale’s experimental Task.
A Task is a structure that models asynchronous actions, including their resource management and cancellation. This means that, if a Task is cancelled before it finishes executing, any resources it allocated will be properly disposed of. Even when combined with other tasks, or transformed by other functions.
The documentation for the concurrency/task
module describes this in details.