function letrec(definition) {
  // We must use a lazy dictionary because we do not know the key set
  // before calling the definition.
  var lazyArbs = {};

  function tie(name) {
    if (!lazyArbs.hasOwnProperty(name)) {
      lazyArbs[name] = lazyArbitrary();
    }
    return lazyArbs[name];
  }

  var strictArbs = definition(tie);

  Object.keys(lazyArbs).forEach(function (key) {
    var strictArb = strictArbs[key];
    if (!strictArb) {
      throw new Error("undefined lazy arbitrary: " + key);
    }
    lazyArbs[key].strict = strictArb;
  });

  return strictArbs;
}
- ```js
    letrec(
      (tie: key -> (arbitrary a | arbitrary b | ...))
      -> { key: arbitrary a, key: arbitrary b, ... }):
    { key: arbitrary a, key: arbitrary b, ... }
    ```

    Mutually recursive definitions. Every reference to a sibling arbitrary
    should go through the `tie` function.

    ```js
    { arb1, arb2 } = jsc.letrec(function (tie) {
      return {
        arb1: jsc.tuple(jsc.int, jsc.oneof(jsc.const(null), tie("arb2"))),
        arb2: jsc.tuple(jsc.bool, jsc.oneof(jsc.const(null), tie("arb1"))),
      }
    });
    ```