Plaid – Blog | Seeking refuge from unsafe JavaScript

原文出处 Plaid – Blog | Seeking refuge from unsafe JavaScript

Seeking refuge from unsafe JavaScript



Date


Apr 26, 2016

Author


David

I joined Plaid in December 2013. At that time, the vast majority of Plaid’s code was JavaScript. Though the proportion has decreased since then, JavaScript still accounts for more than half our code.

Early Plaid code was fairly typical imperative JavaScript. For example:

module.exports = function(raw)
{
  var o = {};

  for (var i = 0; i  Just('x') ~~~| map(toUpper) |~~> Just('X')
                   +------+                 +--------------+

                   +------+                 +--------------+
             [] ~~~| head |~~> Nothing() ~~~| map(toUpper) |~~> Nothing()
                   +------+                 +--------------+

To quench my thirst for type safety I defined safe versions of several unsafe Ramda functions (including head). Initially these lived in a file of helper functions in one Plaid project. We realized these would be useful in other projects and to people outside the company, so we released Sanctuary on GitHub and npm. Now, with Ramda and Sanctuary, it’s possible to write terse, declarative programs that work correctly for all inputs.

S.pipe([S.gets(String, ['transaction_info', 'amount']),
        R.chain(N.normalizeAmount),
        R.map(S.negate),
        S.or,
        R.over(L.amount)])

This function, of type Object → Tx → Tx, describes a sequence of transformations to safely extract a particular value from an Object, and possibly update the value of the amount field of a Tx value.

It acknowledges the following possibilities:

  • the transaction_info field may be absent;

  • the value of the transaction_info field may be null or undefined;

  • the amount field may be absent;

  • the value of the amount field may not be of type String (the argument type required by N.normalizeAmount); and

  • the value of the amount field may not actually represent an amount.

It does so with the Maybe data type rather than with incoherent guards and exception handling.

Although Sanctuary was initially developed internally, several people from outside Plaid have become valued collaborators since we released the project under the MIT license. Stefano Vozza was the first external contributor (documenting much of what was a completely undocumented API at the time), and remains one of the most active. Kevin Wallace contributed the wonderful multi-line error messages:

S.fromMaybe(0, S.Just('XXX'));
// ! TypeError: Type-variable constraint violation
//
//   fromMaybe :: a -> Maybe a -> a
//                ^          ^
//                1          2
//
//   1)  0 :: Number, FiniteNumber, Integer, ValidNumber
//
//   2)  "XXX" :: String
//
//   Since there is no type of which all the above values are members, the type-variable constraint has been violated.

In recognition of the fact that the Sanctuary community is now self-sustaining, we’ve transferred the repositories to the sanctuary-js organization on GitHub.

I believe these projects have an important role to play in the future of functional programming in JavaScript, and in exposing JavaScript programmers to ideas from other languages. I’ll continue to work alongside other members of the community to improve our refuge from unsafe JavaScript.

Integrate Today