Index: imaps-frontend/node_modules/immutable/dist/immutable.d.ts
===================================================================
--- imaps-frontend/node_modules/immutable/dist/immutable.d.ts	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
+++ imaps-frontend/node_modules/immutable/dist/immutable.d.ts	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
@@ -0,0 +1,6105 @@
+/** @ignore we should disable this rules, but let's activate it to enable eslint first */
+/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types */
+/**
+ * Immutable data encourages pure functions (data-in, data-out) and lends itself
+ * to much simpler application development and enabling techniques from
+ * functional programming such as lazy evaluation.
+ *
+ * While designed to bring these powerful functional concepts to JavaScript, it
+ * presents an Object-Oriented API familiar to Javascript engineers and closely
+ * mirroring that of Array, Map, and Set. It is easy and efficient to convert to
+ * and from plain Javascript types.
+ *
+ * ## How to read these docs
+ *
+ * In order to better explain what kinds of values the Immutable.js API expects
+ * and produces, this documentation is presented in a statically typed dialect of
+ * JavaScript (like [Flow][] or [TypeScript][]). You *don't need* to use these
+ * type checking tools in order to use Immutable.js, however becoming familiar
+ * with their syntax will help you get a deeper understanding of this API.
+ *
+ * **A few examples and how to read them.**
+ *
+ * All methods describe the kinds of data they accept and the kinds of data
+ * they return. For example a function which accepts two numbers and returns
+ * a number would look like this:
+ *
+ * ```js
+ * sum(first: number, second: number): number
+ * ```
+ *
+ * Sometimes, methods can accept different kinds of data or return different
+ * kinds of data, and this is described with a *type variable*, which is
+ * typically in all-caps. For example, a function which always returns the same
+ * kind of data it was provided would look like this:
+ *
+ * ```js
+ * identity<T>(value: T): T
+ * ```
+ *
+ * Type variables are defined with classes and referred to in methods. For
+ * example, a class that holds onto a value for you might look like this:
+ *
+ * ```js
+ * class Box<T> {
+ *   constructor(value: T)
+ *   getValue(): T
+ * }
+ * ```
+ *
+ * In order to manipulate Immutable data, methods that we're used to affecting
+ * a Collection instead return a new Collection of the same type. The type
+ * `this` refers to the same kind of class. For example, a List which returns
+ * new Lists when you `push` a value onto it might look like:
+ *
+ * ```js
+ * class List<T> {
+ *   push(value: T): this
+ * }
+ * ```
+ *
+ * Many methods in Immutable.js accept values which implement the JavaScript
+ * [Iterable][] protocol, and might appear like `Iterable<string>` for something
+ * which represents sequence of strings. Typically in JavaScript we use plain
+ * Arrays (`[]`) when an Iterable is expected, but also all of the Immutable.js
+ * collections are iterable themselves!
+ *
+ * For example, to get a value deep within a structure of data, we might use
+ * `getIn` which expects an `Iterable` path:
+ *
+ * ```
+ * getIn(path: Iterable<string | number>): unknown
+ * ```
+ *
+ * To use this method, we could pass an array: `data.getIn([ "key", 2 ])`.
+ *
+ *
+ * Note: All examples are presented in the modern [ES2015][] version of
+ * JavaScript. Use tools like Babel to support older browsers.
+ *
+ * For example:
+ *
+ * ```js
+ * // ES2015
+ * const mappedFoo = foo.map(x => x * x);
+ * // ES5
+ * var mappedFoo = foo.map(function (x) { return x * x; });
+ * ```
+ *
+ * [ES2015]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla
+ * [TypeScript]: https://www.typescriptlang.org/
+ * [Flow]: https://flowtype.org/
+ * [Iterable]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols
+ */
+
+declare namespace Immutable {
+  /** @ignore */
+  type OnlyObject<T> = Extract<T, object>;
+
+  /** @ignore */
+  type ContainObject<T> = OnlyObject<T> extends object
+    ? OnlyObject<T> extends never
+      ? false
+      : true
+    : false;
+
+  /**
+   * @ignore
+   *
+   * Used to convert deeply all immutable types to a plain TS type.
+   * Using `unknown` on object instead of recursive call as we have a circular reference issue
+   */
+  export type DeepCopy<T> = T extends Record<infer R>
+    ? // convert Record to DeepCopy plain JS object
+      {
+        [key in keyof R]: ContainObject<R[key]> extends true ? unknown : R[key];
+      }
+    : T extends MapOf<infer R>
+    ? // convert MapOf to DeepCopy plain JS object
+      {
+        [key in keyof R]: ContainObject<R[key]> extends true ? unknown : R[key];
+      }
+    : T extends Collection.Keyed<infer KeyedKey, infer V>
+    ? // convert KeyedCollection to DeepCopy plain JS object
+      {
+        [key in KeyedKey extends string | number | symbol
+          ? KeyedKey
+          : string]: V extends object ? unknown : V;
+      }
+    : // convert IndexedCollection or Immutable.Set to DeepCopy plain JS array
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    T extends Collection<infer _, infer V>
+    ? Array<DeepCopy<V>>
+    : T extends string | number // Iterable scalar types : should be kept as is
+    ? T
+    : T extends Iterable<infer V> // Iterable are converted to plain JS array
+    ? Array<DeepCopy<V>>
+    : T extends object // plain JS object are converted deeply
+    ? {
+        [ObjectKey in keyof T]: ContainObject<T[ObjectKey]> extends true
+          ? unknown
+          : T[ObjectKey];
+      }
+    : // other case : should be kept as is
+      T;
+
+  /**
+   * Describes which item in a pair should be placed first when sorting
+   *
+   * @ignore
+   */
+  export enum PairSorting {
+    LeftThenRight = -1,
+    RightThenLeft = +1,
+  }
+
+  /**
+   * Function comparing two items of the same type. It can return:
+   *
+   * * a PairSorting value, to indicate whether the left-hand item or the right-hand item should be placed before the other
+   *
+   * * the traditional numeric return value - especially -1, 0, or 1
+   *
+   * @ignore
+   */
+  export type Comparator<T> = (left: T, right: T) => PairSorting | number;
+
+  /**
+   * Lists are ordered indexed dense collections, much like a JavaScript
+   * Array.
+   *
+   * Lists are immutable and fully persistent with O(log32 N) gets and sets,
+   * and O(1) push and pop.
+   *
+   * Lists implement Deque, with efficient addition and removal from both the
+   * end (`push`, `pop`) and beginning (`unshift`, `shift`).
+   *
+   * Unlike a JavaScript Array, there is no distinction between an
+   * "unset" index and an index set to `undefined`. `List#forEach` visits all
+   * indices from 0 to size, regardless of whether they were explicitly defined.
+   */
+  namespace List {
+    /**
+     * True if the provided value is a List
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List } = require('immutable');
+     * List.isList([]); // false
+     * List.isList(List()); // true
+     * ```
+     */
+    function isList(maybeList: unknown): maybeList is List<unknown>;
+
+    /**
+     * Creates a new List containing `values`.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List } = require('immutable');
+     * List.of(1, 2, 3, 4)
+     * // List [ 1, 2, 3, 4 ]
+     * ```
+     *
+     * Note: Values are not altered or converted in any way.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List } = require('immutable');
+     * List.of({x:1}, 2, [3], 4)
+     * // List [ { x: 1 }, 2, [ 3 ], 4 ]
+     * ```
+     */
+    function of<T>(...values: Array<T>): List<T>;
+  }
+
+  /**
+   * Create a new immutable List containing the values of the provided
+   * collection-like.
+   *
+   * Note: `List` is a factory function and not a class, and does not use the
+   * `new` keyword during construction.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { List, Set } = require('immutable')
+   *
+   * const emptyList = List()
+   * // List []
+   *
+   * const plainArray = [ 1, 2, 3, 4 ]
+   * const listFromPlainArray = List(plainArray)
+   * // List [ 1, 2, 3, 4 ]
+   *
+   * const plainSet = Set([ 1, 2, 3, 4 ])
+   * const listFromPlainSet = List(plainSet)
+   * // List [ 1, 2, 3, 4 ]
+   *
+   * const arrayIterator = plainArray[Symbol.iterator]()
+   * const listFromCollectionArray = List(arrayIterator)
+   * // List [ 1, 2, 3, 4 ]
+   *
+   * listFromPlainArray.equals(listFromCollectionArray) // true
+   * listFromPlainSet.equals(listFromCollectionArray) // true
+   * listFromPlainSet.equals(listFromPlainArray) // true
+   * ```
+   */
+  function List<T>(collection?: Iterable<T> | ArrayLike<T>): List<T>;
+
+  interface List<T> extends Collection.Indexed<T> {
+    /**
+     * The number of items in this List.
+     */
+    readonly size: number;
+
+    // Persistent changes
+
+    /**
+     * Returns a new List which includes `value` at `index`. If `index` already
+     * exists in this List, it will be replaced.
+     *
+     * `index` may be a negative number, which indexes back from the end of the
+     * List. `v.set(-1, "value")` sets the last item in the List.
+     *
+     * If `index` larger than `size`, the returned List's `size` will be large
+     * enough to include the `index`.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { List } = require('immutable');" }
+     * -->
+     * ```js
+     * const originalList = List([ 0 ]);
+     * // List [ 0 ]
+     * originalList.set(1, 1);
+     * // List [ 0, 1 ]
+     * originalList.set(0, 'overwritten');
+     * // List [ "overwritten" ]
+     * originalList.set(2, 2);
+     * // List [ 0, undefined, 2 ]
+     *
+     * List().set(50000, 'value').size;
+     * // 50001
+     * ```
+     *
+     * Note: `set` can be used in `withMutations`.
+     */
+    set(index: number, value: T): List<T>;
+
+    /**
+     * Returns a new List which excludes this `index` and with a size 1 less
+     * than this List. Values at indices above `index` are shifted down by 1 to
+     * fill the position.
+     *
+     * This is synonymous with `list.splice(index, 1)`.
+     *
+     * `index` may be a negative number, which indexes back from the end of the
+     * List. `v.delete(-1)` deletes the last item in the List.
+     *
+     * Note: `delete` cannot be safely used in IE8
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { List } = require('immutable');" }
+     * -->
+     * ```js
+     * List([ 0, 1, 2, 3, 4 ]).delete(0);
+     * // List [ 1, 2, 3, 4 ]
+     * ```
+     *
+     * Since `delete()` re-indexes values, it produces a complete copy, which
+     * has `O(N)` complexity.
+     *
+     * Note: `delete` *cannot* be used in `withMutations`.
+     *
+     * @alias remove
+     */
+    delete(index: number): List<T>;
+    remove(index: number): List<T>;
+
+    /**
+     * Returns a new List with `value` at `index` with a size 1 more than this
+     * List. Values at indices above `index` are shifted over by 1.
+     *
+     * This is synonymous with `list.splice(index, 0, value)`.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { List } = require('immutable');" }
+     * -->
+     * ```js
+     * List([ 0, 1, 2, 3, 4 ]).insert(6, 5)
+     * // List [ 0, 1, 2, 3, 4, 5 ]
+     * ```
+     *
+     * Since `insert()` re-indexes values, it produces a complete copy, which
+     * has `O(N)` complexity.
+     *
+     * Note: `insert` *cannot* be used in `withMutations`.
+     */
+    insert(index: number, value: T): List<T>;
+
+    /**
+     * Returns a new List with 0 size and no values in constant time.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { List } = require('immutable');" }
+     * -->
+     * ```js
+     * List([ 1, 2, 3, 4 ]).clear()
+     * // List []
+     * ```
+     *
+     * Note: `clear` can be used in `withMutations`.
+     */
+    clear(): List<T>;
+
+    /**
+     * Returns a new List with the provided `values` appended, starting at this
+     * List's `size`.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { List } = require('immutable');" }
+     * -->
+     * ```js
+     * List([ 1, 2, 3, 4 ]).push(5)
+     * // List [ 1, 2, 3, 4, 5 ]
+     * ```
+     *
+     * Note: `push` can be used in `withMutations`.
+     */
+    push(...values: Array<T>): List<T>;
+
+    /**
+     * Returns a new List with a size ones less than this List, excluding
+     * the last index in this List.
+     *
+     * Note: this differs from `Array#pop` because it returns a new
+     * List rather than the removed value. Use `last()` to get the last value
+     * in this List.
+     *
+     * ```js
+     * List([ 1, 2, 3, 4 ]).pop()
+     * // List[ 1, 2, 3 ]
+     * ```
+     *
+     * Note: `pop` can be used in `withMutations`.
+     */
+    pop(): List<T>;
+
+    /**
+     * Returns a new List with the provided `values` prepended, shifting other
+     * values ahead to higher indices.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { List } = require('immutable');" }
+     * -->
+     * ```js
+     * List([ 2, 3, 4]).unshift(1);
+     * // List [ 1, 2, 3, 4 ]
+     * ```
+     *
+     * Note: `unshift` can be used in `withMutations`.
+     */
+    unshift(...values: Array<T>): List<T>;
+
+    /**
+     * Returns a new List with a size ones less than this List, excluding
+     * the first index in this List, shifting all other values to a lower index.
+     *
+     * Note: this differs from `Array#shift` because it returns a new
+     * List rather than the removed value. Use `first()` to get the first
+     * value in this List.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { List } = require('immutable');" }
+     * -->
+     * ```js
+     * List([ 0, 1, 2, 3, 4 ]).shift();
+     * // List [ 1, 2, 3, 4 ]
+     * ```
+     *
+     * Note: `shift` can be used in `withMutations`.
+     */
+    shift(): List<T>;
+
+    /**
+     * Returns a new List with an updated value at `index` with the return
+     * value of calling `updater` with the existing value, or `notSetValue` if
+     * `index` was not set. If called with a single argument, `updater` is
+     * called with the List itself.
+     *
+     * `index` may be a negative number, which indexes back from the end of the
+     * List. `v.update(-1)` updates the last item in the List.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { List } = require('immutable');" }
+     * -->
+     * ```js
+     * const list = List([ 'a', 'b', 'c' ])
+     * const result = list.update(2, val => val.toUpperCase())
+     * // List [ "a", "b", "C" ]
+     * ```
+     *
+     * This can be very useful as a way to "chain" a normal function into a
+     * sequence of methods. RxJS calls this "let" and lodash calls it "thru".
+     *
+     * For example, to sum a List after mapping and filtering:
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { List } = require('immutable');" }
+     * -->
+     * ```js
+     * function sum(collection) {
+     *   return collection.reduce((sum, x) => sum + x, 0)
+     * }
+     *
+     * List([ 1, 2, 3 ])
+     *   .map(x => x + 1)
+     *   .filter(x => x % 2 === 0)
+     *   .update(sum)
+     * // 6
+     * ```
+     *
+     * Note: `update(index)` can be used in `withMutations`.
+     *
+     * @see `Map#update`
+     */
+    update(index: number, notSetValue: T, updater: (value: T) => T): this;
+    update(
+      index: number,
+      updater: (value: T | undefined) => T | undefined
+    ): this;
+    update<R>(updater: (value: this) => R): R;
+
+    /**
+     * Returns a new List with size `size`. If `size` is less than this
+     * List's size, the new List will exclude values at the higher indices.
+     * If `size` is greater than this List's size, the new List will have
+     * undefined values for the newly available indices.
+     *
+     * When building a new List and the final size is known up front, `setSize`
+     * used in conjunction with `withMutations` may result in the more
+     * performant construction.
+     */
+    setSize(size: number): List<T>;
+
+    // Deep persistent changes
+
+    /**
+     * Returns a new List having set `value` at this `keyPath`. If any keys in
+     * `keyPath` do not exist, a new immutable Map will be created at that key.
+     *
+     * Index numbers are used as keys to determine the path to follow in
+     * the List.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List } = require('immutable')
+     * const list = List([ 0, 1, 2, List([ 3, 4 ])])
+     * list.setIn([3, 0], 999);
+     * // List [ 0, 1, 2, List [ 999, 4 ] ]
+     * ```
+     *
+     * Plain JavaScript Object or Arrays may be nested within an Immutable.js
+     * Collection, and setIn() can update those values as well, treating them
+     * immutably by creating new copies of those values with the changes applied.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List } = require('immutable')
+     * const list = List([ 0, 1, 2, { plain: 'object' }])
+     * list.setIn([3, 'plain'], 'value');
+     * // List([ 0, 1, 2, { plain: 'value' }])
+     * ```
+     *
+     * Note: `setIn` can be used in `withMutations`.
+     */
+    setIn(keyPath: Iterable<unknown>, value: unknown): this;
+
+    /**
+     * Returns a new List having removed the value at this `keyPath`. If any
+     * keys in `keyPath` do not exist, no change will occur.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List } = require('immutable')
+     * const list = List([ 0, 1, 2, List([ 3, 4 ])])
+     * list.deleteIn([3, 0]);
+     * // List [ 0, 1, 2, List [ 4 ] ]
+     * ```
+     *
+     * Plain JavaScript Object or Arrays may be nested within an Immutable.js
+     * Collection, and removeIn() can update those values as well, treating them
+     * immutably by creating new copies of those values with the changes applied.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List } = require('immutable')
+     * const list = List([ 0, 1, 2, { plain: 'object' }])
+     * list.removeIn([3, 'plain']);
+     * // List([ 0, 1, 2, {}])
+     * ```
+     *
+     * Note: `deleteIn` *cannot* be safely used in `withMutations`.
+     *
+     * @alias removeIn
+     */
+    deleteIn(keyPath: Iterable<unknown>): this;
+    removeIn(keyPath: Iterable<unknown>): this;
+
+    /**
+     * Note: `updateIn` can be used in `withMutations`.
+     *
+     * @see `Map#updateIn`
+     */
+    updateIn(
+      keyPath: Iterable<unknown>,
+      notSetValue: unknown,
+      updater: (value: unknown) => unknown
+    ): this;
+    updateIn(
+      keyPath: Iterable<unknown>,
+      updater: (value: unknown) => unknown
+    ): this;
+
+    /**
+     * Note: `mergeIn` can be used in `withMutations`.
+     *
+     * @see `Map#mergeIn`
+     */
+    mergeIn(keyPath: Iterable<unknown>, ...collections: Array<unknown>): this;
+
+    /**
+     * Note: `mergeDeepIn` can be used in `withMutations`.
+     *
+     * @see `Map#mergeDeepIn`
+     */
+    mergeDeepIn(
+      keyPath: Iterable<unknown>,
+      ...collections: Array<unknown>
+    ): this;
+
+    // Transient changes
+
+    /**
+     * Note: Not all methods can be safely used on a mutable collection or within
+     * `withMutations`! Check the documentation for each method to see if it
+     * allows being used in `withMutations`.
+     *
+     * @see `Map#withMutations`
+     */
+    withMutations(mutator: (mutable: this) => unknown): this;
+
+    /**
+     * An alternative API for withMutations()
+     *
+     * Note: Not all methods can be safely used on a mutable collection or within
+     * `withMutations`! Check the documentation for each method to see if it
+     * allows being used in `withMutations`.
+     *
+     * @see `Map#asMutable`
+     */
+    asMutable(): this;
+
+    /**
+     * @see `Map#wasAltered`
+     */
+    wasAltered(): boolean;
+
+    /**
+     * @see `Map#asImmutable`
+     */
+    asImmutable(): this;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new List with other values or collections concatenated to this one.
+     *
+     * Note: `concat` can be used in `withMutations`.
+     *
+     * @alias merge
+     */
+    concat<C>(...valuesOrCollections: Array<Iterable<C> | C>): List<T | C>;
+    merge<C>(...collections: Array<Iterable<C>>): List<T | C>;
+
+    /**
+     * Returns a new List with values passed through a
+     * `mapper` function.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { List } = require('immutable');" }
+     * -->
+     * ```js
+     * List([ 1, 2 ]).map(x => 10 * x)
+     * // List [ 10, 20 ]
+     * ```
+     */
+    map<M>(
+      mapper: (value: T, key: number, iter: this) => M,
+      context?: unknown
+    ): List<M>;
+
+    /**
+     * Flat-maps the List, returning a new List.
+     *
+     * Similar to `list.map(...).flatten(true)`.
+     */
+    flatMap<M>(
+      mapper: (value: T, key: number, iter: this) => Iterable<M>,
+      context?: unknown
+    ): List<M>;
+
+    /**
+     * Returns a new List with only the values for which the `predicate`
+     * function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends T>(
+      predicate: (value: T, index: number, iter: this) => value is F,
+      context?: unknown
+    ): List<F>;
+    filter(
+      predicate: (value: T, index: number, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new List with the values for which the `predicate`
+     * function returns false and another for which is returns true.
+     */
+    partition<F extends T, C>(
+      predicate: (this: C, value: T, index: number, iter: this) => value is F,
+      context?: C
+    ): [List<T>, List<F>];
+    partition<C>(
+      predicate: (this: C, value: T, index: number, iter: this) => unknown,
+      context?: C
+    ): [this, this];
+
+    /**
+     * Returns a List "zipped" with the provided collection.
+     *
+     * Like `zipWith`, but using the default `zipper`: creating an `Array`.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { List } = require('immutable');" }
+     * -->
+     * ```js
+     * const a = List([ 1, 2, 3 ]);
+     * const b = List([ 4, 5, 6 ]);
+     * const c = a.zip(b); // List [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
+     * ```
+     */
+    zip<U>(other: Collection<unknown, U>): List<[T, U]>;
+    zip<U, V>(
+      other: Collection<unknown, U>,
+      other2: Collection<unknown, V>
+    ): List<[T, U, V]>;
+    zip(...collections: Array<Collection<unknown, unknown>>): List<unknown>;
+
+    /**
+     * Returns a List "zipped" with the provided collections.
+     *
+     * Unlike `zip`, `zipAll` continues zipping until the longest collection is
+     * exhausted. Missing values from shorter collections are filled with `undefined`.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { List } = require('immutable');" }
+     * -->
+     * ```js
+     * const a = List([ 1, 2 ]);
+     * const b = List([ 3, 4, 5 ]);
+     * const c = a.zipAll(b); // List [ [ 1, 3 ], [ 2, 4 ], [ undefined, 5 ] ]
+     * ```
+     *
+     * Note: Since zipAll will return a collection as large as the largest
+     * input, some results may contain undefined values. TypeScript cannot
+     * account for these without cases (as of v2.5).
+     */
+    zipAll<U>(other: Collection<unknown, U>): List<[T, U]>;
+    zipAll<U, V>(
+      other: Collection<unknown, U>,
+      other2: Collection<unknown, V>
+    ): List<[T, U, V]>;
+    zipAll(...collections: Array<Collection<unknown, unknown>>): List<unknown>;
+
+    /**
+     * Returns a List "zipped" with the provided collections by using a
+     * custom `zipper` function.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { List } = require('immutable');" }
+     * -->
+     * ```js
+     * const a = List([ 1, 2, 3 ]);
+     * const b = List([ 4, 5, 6 ]);
+     * const c = a.zipWith((a, b) => a + b, b);
+     * // List [ 5, 7, 9 ]
+     * ```
+     */
+    zipWith<U, Z>(
+      zipper: (value: T, otherValue: U) => Z,
+      otherCollection: Collection<unknown, U>
+    ): List<Z>;
+    zipWith<U, V, Z>(
+      zipper: (value: T, otherValue: U, thirdValue: V) => Z,
+      otherCollection: Collection<unknown, U>,
+      thirdCollection: Collection<unknown, V>
+    ): List<Z>;
+    zipWith<Z>(
+      zipper: (...values: Array<unknown>) => Z,
+      ...collections: Array<Collection<unknown, unknown>>
+    ): List<Z>;
+  }
+
+  /**
+   * Immutable Map is an unordered Collection.Keyed of (key, value) pairs with
+   * `O(log32 N)` gets and `O(log32 N)` persistent sets.
+   *
+   * Iteration order of a Map is undefined, however is stable. Multiple
+   * iterations of the same Map will iterate in the same order.
+   *
+   * Map's keys can be of any type, and use `Immutable.is` to determine key
+   * equality. This allows the use of any value (including NaN) as a key.
+   *
+   * Because `Immutable.is` returns equality based on value semantics, and
+   * Immutable collections are treated as values, any Immutable collection may
+   * be used as a key.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { Map, List } = require('immutable');
+   * Map().set(List([ 1 ]), 'listofone').get(List([ 1 ]));
+   * // 'listofone'
+   * ```
+   *
+   * Any JavaScript object may be used as a key, however strict identity is used
+   * to evaluate key equality. Two similar looking objects will represent two
+   * different keys.
+   *
+   * Implemented by a hash-array mapped trie.
+   */
+  namespace Map {
+    /**
+     * True if the provided value is a Map
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * Map.isMap({}) // false
+     * Map.isMap(Map()) // true
+     * ```
+     */
+    function isMap(maybeMap: unknown): maybeMap is Map<unknown, unknown>;
+  }
+
+  /**
+   * Creates a new Immutable Map.
+   *
+   * Created with the same key value pairs as the provided Collection.Keyed or
+   * JavaScript Object or expects a Collection of [K, V] tuple entries.
+   *
+   * Note: `Map` is a factory function and not a class, and does not use the
+   * `new` keyword during construction.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { Map } = require('immutable')
+   * Map({ key: "value" })
+   * Map([ [ "key", "value" ] ])
+   * ```
+   *
+   * Keep in mind, when using JS objects to construct Immutable Maps, that
+   * JavaScript Object properties are always strings, even if written in a
+   * quote-less shorthand, while Immutable Maps accept keys of any type.
+   *
+   * <!-- runkit:activate
+   *      { "preamble": "const { Map } = require('immutable');" }
+   * -->
+   * ```js
+   * let obj = { 1: "one" }
+   * Object.keys(obj) // [ "1" ]
+   * assert.equal(obj["1"], obj[1]) // "one" === "one"
+   *
+   * let map = Map(obj)
+   * assert.notEqual(map.get("1"), map.get(1)) // "one" !== undefined
+   * ```
+   *
+   * Property access for JavaScript Objects first converts the key to a string,
+   * but since Immutable Map keys can be of any type the argument to `get()` is
+   * not altered.
+   */
+  function Map<K, V>(collection?: Iterable<[K, V]>): Map<K, V>;
+  function Map<R extends { [key in string | number | symbol]: unknown }>(
+    obj: R
+  ): MapOf<R>;
+  function Map<V>(obj: { [key: string]: V }): Map<string, V>;
+  function Map<K extends string | symbol, V>(obj: { [P in K]?: V }): Map<K, V>;
+
+  /**
+   * Represent a Map constructed by an object
+   *
+   * @ignore
+   */
+  interface MapOf<R extends { [key in string | number | symbol]: unknown }>
+    extends Map<keyof R, R[keyof R]> {
+    /**
+     * Returns the value associated with the provided key, or notSetValue if
+     * the Collection does not contain this key.
+     *
+     * Note: it is possible a key may be associated with an `undefined` value,
+     * so if `notSetValue` is not provided and this method returns `undefined`,
+     * that does not guarantee the key was not found.
+     */
+    get<K extends keyof R>(key: K, notSetValue?: unknown): R[K];
+    get<NSV>(key: any, notSetValue: NSV): NSV;
+
+    // TODO `<const P extends ...>` can be used after dropping support for TypeScript 4.x
+    // reference: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html#const-type-parameters
+    // after this change, `as const` assertions can be remove from the type tests
+    getIn<P extends ReadonlyArray<string | number | symbol>>(
+      searchKeyPath: [...P],
+      notSetValue?: unknown
+    ): RetrievePath<R, P>;
+
+    set<K extends keyof R>(key: K, value: R[K]): this;
+
+    update(updater: (value: this) => this): this;
+    update<K extends keyof R>(key: K, updater: (value: R[K]) => R[K]): this;
+    update<K extends keyof R, NSV extends R[K]>(
+      key: K,
+      notSetValue: NSV,
+      updater: (value: R[K]) => R[K]
+    ): this;
+
+    // Possible best type is MapOf<Omit<R, K>> but Omit seems to broke other function calls
+    // and generate recursion error with other methods (update, merge, etc.) until those functions are defined in MapOf
+    delete<K extends keyof R>(
+      key: K
+    ): Extract<R[K], undefined> extends never ? never : this;
+    remove<K extends keyof R>(
+      key: K
+    ): Extract<R[K], undefined> extends never ? never : this;
+
+    toJS(): { [K in keyof R]: DeepCopy<R[K]> };
+
+    toJSON(): { [K in keyof R]: R[K] };
+  }
+
+  // Loosely based off of this work.
+  // https://github.com/immutable-js/immutable-js/issues/1462#issuecomment-584123268
+
+  /** @ignore */
+  type GetMapType<S> = S extends MapOf<infer T> ? T : S;
+
+  /** @ignore */
+  type Head<T extends ReadonlyArray<any>> = T extends [
+    infer H,
+    ...Array<unknown>
+  ]
+    ? H
+    : never;
+
+  /** @ignore */
+  type Tail<T extends ReadonlyArray<any>> = T extends [unknown, ...infer I]
+    ? I
+    : Array<never>;
+
+  /** @ignore */
+  type RetrievePathReducer<
+    T,
+    C,
+    L extends ReadonlyArray<any>
+  > = C extends keyof GetMapType<T>
+    ? L extends []
+      ? GetMapType<T>[C]
+      : RetrievePathReducer<GetMapType<T>[C], Head<L>, Tail<L>>
+    : never;
+
+  /** @ignore */
+  type RetrievePath<
+    R,
+    P extends ReadonlyArray<string | number | symbol>
+  > = P extends [] ? P : RetrievePathReducer<R, Head<P>, Tail<P>>;
+
+  interface Map<K, V> extends Collection.Keyed<K, V> {
+    /**
+     * The number of entries in this Map.
+     */
+    readonly size: number;
+
+    // Persistent changes
+
+    /**
+     * Returns a new Map also containing the new key, value pair. If an equivalent
+     * key already exists in this Map, it will be replaced.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * const originalMap = Map()
+     * const newerMap = originalMap.set('key', 'value')
+     * const newestMap = newerMap.set('key', 'newer value')
+     *
+     * originalMap
+     * // Map {}
+     * newerMap
+     * // Map { "key": "value" }
+     * newestMap
+     * // Map { "key": "newer value" }
+     * ```
+     *
+     * Note: `set` can be used in `withMutations`.
+     */
+    set(key: K, value: V): this;
+
+    /**
+     * Returns a new Map which excludes this `key`.
+     *
+     * Note: `delete` cannot be safely used in IE8, but is provided to mirror
+     * the ES6 collection API.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * const originalMap = Map({
+     *   key: 'value',
+     *   otherKey: 'other value'
+     * })
+     * // Map { "key": "value", "otherKey": "other value" }
+     * originalMap.delete('otherKey')
+     * // Map { "key": "value" }
+     * ```
+     *
+     * Note: `delete` can be used in `withMutations`.
+     *
+     * @alias remove
+     */
+    delete(key: K): this;
+    remove(key: K): this;
+
+    /**
+     * Returns a new Map which excludes the provided `keys`.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * const names = Map({ a: "Aaron", b: "Barry", c: "Connor" })
+     * names.deleteAll([ 'a', 'c' ])
+     * // Map { "b": "Barry" }
+     * ```
+     *
+     * Note: `deleteAll` can be used in `withMutations`.
+     *
+     * @alias removeAll
+     */
+    deleteAll(keys: Iterable<K>): this;
+    removeAll(keys: Iterable<K>): this;
+
+    /**
+     * Returns a new Map containing no keys or values.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * Map({ key: 'value' }).clear()
+     * // Map {}
+     * ```
+     *
+     * Note: `clear` can be used in `withMutations`.
+     */
+    clear(): this;
+
+    /**
+     * Returns a new Map having updated the value at this `key` with the return
+     * value of calling `updater` with the existing value.
+     *
+     * Similar to: `map.set(key, updater(map.get(key)))`.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * const aMap = Map({ key: 'value' })
+     * const newMap = aMap.update('key', value => value + value)
+     * // Map { "key": "valuevalue" }
+     * ```
+     *
+     * This is most commonly used to call methods on collections within a
+     * structure of data. For example, in order to `.push()` onto a nested `List`,
+     * `update` and `push` can be used together:
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { Map, List } = require('immutable');" }
+     * -->
+     * ```js
+     * const aMap = Map({ nestedList: List([ 1, 2, 3 ]) })
+     * const newMap = aMap.update('nestedList', list => list.push(4))
+     * // Map { "nestedList": List [ 1, 2, 3, 4 ] }
+     * ```
+     *
+     * When a `notSetValue` is provided, it is provided to the `updater`
+     * function when the value at the key does not exist in the Map.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { Map } = require('immutable');" }
+     * -->
+     * ```js
+     * const aMap = Map({ key: 'value' })
+     * const newMap = aMap.update('noKey', 'no value', value => value + value)
+     * // Map { "key": "value", "noKey": "no valueno value" }
+     * ```
+     *
+     * However, if the `updater` function returns the same value it was called
+     * with, then no change will occur. This is still true if `notSetValue`
+     * is provided.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { Map } = require('immutable');" }
+     * -->
+     * ```js
+     * const aMap = Map({ apples: 10 })
+     * const newMap = aMap.update('oranges', 0, val => val)
+     * // Map { "apples": 10 }
+     * assert.strictEqual(newMap, map);
+     * ```
+     *
+     * For code using ES2015 or later, using `notSetValue` is discourged in
+     * favor of function parameter default values. This helps to avoid any
+     * potential confusion with identify functions as described above.
+     *
+     * The previous example behaves differently when written with default values:
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { Map } = require('immutable');" }
+     * -->
+     * ```js
+     * const aMap = Map({ apples: 10 })
+     * const newMap = aMap.update('oranges', (val = 0) => val)
+     * // Map { "apples": 10, "oranges": 0 }
+     * ```
+     *
+     * If no key is provided, then the `updater` function return value is
+     * returned as well.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { Map } = require('immutable');" }
+     * -->
+     * ```js
+     * const aMap = Map({ key: 'value' })
+     * const result = aMap.update(aMap => aMap.get('key'))
+     * // "value"
+     * ```
+     *
+     * This can be very useful as a way to "chain" a normal function into a
+     * sequence of methods. RxJS calls this "let" and lodash calls it "thru".
+     *
+     * For example, to sum the values in a Map
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { Map } = require('immutable');" }
+     * -->
+     * ```js
+     * function sum(collection) {
+     *   return collection.reduce((sum, x) => sum + x, 0)
+     * }
+     *
+     * Map({ x: 1, y: 2, z: 3 })
+     *   .map(x => x + 1)
+     *   .filter(x => x % 2 === 0)
+     *   .update(sum)
+     * // 6
+     * ```
+     *
+     * Note: `update(key)` can be used in `withMutations`.
+     */
+    update(key: K, notSetValue: V, updater: (value: V) => V): this;
+    update(key: K, updater: (value: V | undefined) => V | undefined): this;
+    update<R>(updater: (value: this) => R): R;
+
+    /**
+     * Returns a new Map resulting from merging the provided Collections
+     * (or JS objects) into this Map. In other words, this takes each entry of
+     * each collection and sets it on this Map.
+     *
+     * Note: Values provided to `merge` are shallowly converted before being
+     * merged. No nested values are altered.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * const one = Map({ a: 10, b: 20, c: 30 })
+     * const two = Map({ b: 40, a: 50, d: 60 })
+     * one.merge(two) // Map { "a": 50, "b": 40, "c": 30, "d": 60 }
+     * two.merge(one) // Map { "b": 20, "a": 10, "d": 60, "c": 30 }
+     * ```
+     *
+     * Note: `merge` can be used in `withMutations`.
+     *
+     * @alias concat
+     */
+    merge<KC, VC>(
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): Map<K | KC, Exclude<V, VC> | VC>;
+    merge<C>(
+      ...collections: Array<{ [key: string]: C }>
+    ): Map<K | string, Exclude<V, C> | C>;
+
+    concat<KC, VC>(
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): Map<K | KC, Exclude<V, VC> | VC>;
+    concat<C>(
+      ...collections: Array<{ [key: string]: C }>
+    ): Map<K | string, Exclude<V, C> | C>;
+
+    /**
+     * Like `merge()`, `mergeWith()` returns a new Map resulting from merging
+     * the provided Collections (or JS objects) into this Map, but uses the
+     * `merger` function for dealing with conflicts.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * const one = Map({ a: 10, b: 20, c: 30 })
+     * const two = Map({ b: 40, a: 50, d: 60 })
+     * one.mergeWith((oldVal, newVal) => oldVal / newVal, two)
+     * // { "a": 0.2, "b": 0.5, "c": 30, "d": 60 }
+     * two.mergeWith((oldVal, newVal) => oldVal / newVal, one)
+     * // { "b": 2, "a": 5, "d": 60, "c": 30 }
+     * ```
+     *
+     * Note: `mergeWith` can be used in `withMutations`.
+     */
+    mergeWith<KC, VC, VCC>(
+      merger: (oldVal: V, newVal: VC, key: K) => VCC,
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): Map<K | KC, V | VC | VCC>;
+    mergeWith<C, CC>(
+      merger: (oldVal: V, newVal: C, key: string) => CC,
+      ...collections: Array<{ [key: string]: C }>
+    ): Map<K | string, V | C | CC>;
+
+    /**
+     * Like `merge()`, but when two compatible collections are encountered with
+     * the same key, it merges them as well, recursing deeply through the nested
+     * data. Two collections are considered to be compatible (and thus will be
+     * merged together) if they both fall into one of three categories: keyed
+     * (e.g., `Map`s, `Record`s, and objects), indexed (e.g., `List`s and
+     * arrays), or set-like (e.g., `Set`s). If they fall into separate
+     * categories, `mergeDeep` will replace the existing collection with the
+     * collection being merged in. This behavior can be customized by using
+     * `mergeDeepWith()`.
+     *
+     * Note: Indexed and set-like collections are merged using
+     * `concat()`/`union()` and therefore do not recurse.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * const one = Map({ a: Map({ x: 10, y: 10 }), b: Map({ x: 20, y: 50 }) })
+     * const two = Map({ a: Map({ x: 2 }), b: Map({ y: 5 }), c: Map({ z: 3 }) })
+     * one.mergeDeep(two)
+     * // Map {
+     * //   "a": Map { "x": 2, "y": 10 },
+     * //   "b": Map { "x": 20, "y": 5 },
+     * //   "c": Map { "z": 3 }
+     * // }
+     * ```
+     *
+     * Note: `mergeDeep` can be used in `withMutations`.
+     */
+    mergeDeep<KC, VC>(
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): Map<K | KC, V | VC>;
+    mergeDeep<C>(
+      ...collections: Array<{ [key: string]: C }>
+    ): Map<K | string, V | C>;
+
+    /**
+     * Like `mergeDeep()`, but when two non-collections or incompatible
+     * collections are encountered at the same key, it uses the `merger`
+     * function to determine the resulting value. Collections are considered
+     * incompatible if they fall into separate categories between keyed,
+     * indexed, and set-like.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * const one = Map({ a: Map({ x: 10, y: 10 }), b: Map({ x: 20, y: 50 }) })
+     * const two = Map({ a: Map({ x: 2 }), b: Map({ y: 5 }), c: Map({ z: 3 }) })
+     * one.mergeDeepWith((oldVal, newVal) => oldVal / newVal, two)
+     * // Map {
+     * //   "a": Map { "x": 5, "y": 10 },
+     * //   "b": Map { "x": 20, "y": 10 },
+     * //   "c": Map { "z": 3 }
+     * // }
+     * ```
+     *
+     * Note: `mergeDeepWith` can be used in `withMutations`.
+     */
+    mergeDeepWith(
+      merger: (oldVal: unknown, newVal: unknown, key: unknown) => unknown,
+      ...collections: Array<Iterable<[K, V]> | { [key: string]: V }>
+    ): this;
+
+    // Deep persistent changes
+
+    /**
+     * Returns a new Map having set `value` at this `keyPath`. If any keys in
+     * `keyPath` do not exist, a new immutable Map will be created at that key.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * const originalMap = Map({
+     *   subObject: Map({
+     *     subKey: 'subvalue',
+     *     subSubObject: Map({
+     *       subSubKey: 'subSubValue'
+     *     })
+     *   })
+     * })
+     *
+     * const newMap = originalMap.setIn(['subObject', 'subKey'], 'ha ha!')
+     * // Map {
+     * //   "subObject": Map {
+     * //     "subKey": "ha ha!",
+     * //     "subSubObject": Map { "subSubKey": "subSubValue" }
+     * //   }
+     * // }
+     *
+     * const newerMap = originalMap.setIn(
+     *   ['subObject', 'subSubObject', 'subSubKey'],
+     *   'ha ha ha!'
+     * )
+     * // Map {
+     * //   "subObject": Map {
+     * //     "subKey": "subvalue",
+     * //     "subSubObject": Map { "subSubKey": "ha ha ha!" }
+     * //   }
+     * // }
+     * ```
+     *
+     * Plain JavaScript Object or Arrays may be nested within an Immutable.js
+     * Collection, and setIn() can update those values as well, treating them
+     * immutably by creating new copies of those values with the changes applied.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * const originalMap = Map({
+     *   subObject: {
+     *     subKey: 'subvalue',
+     *     subSubObject: {
+     *       subSubKey: 'subSubValue'
+     *     }
+     *   }
+     * })
+     *
+     * originalMap.setIn(['subObject', 'subKey'], 'ha ha!')
+     * // Map {
+     * //   "subObject": {
+     * //     subKey: "ha ha!",
+     * //     subSubObject: { subSubKey: "subSubValue" }
+     * //   }
+     * // }
+     * ```
+     *
+     * If any key in the path exists but cannot be updated (such as a primitive
+     * like number or a custom Object like Date), an error will be thrown.
+     *
+     * Note: `setIn` can be used in `withMutations`.
+     */
+    setIn(keyPath: Iterable<unknown>, value: unknown): this;
+
+    /**
+     * Returns a new Map having removed the value at this `keyPath`. If any keys
+     * in `keyPath` do not exist, no change will occur.
+     *
+     * Note: `deleteIn` can be used in `withMutations`.
+     *
+     * @alias removeIn
+     */
+    deleteIn(keyPath: Iterable<unknown>): this;
+    removeIn(keyPath: Iterable<unknown>): this;
+
+    /**
+     * Returns a new Map having applied the `updater` to the entry found at the
+     * keyPath.
+     *
+     * This is most commonly used to call methods on collections nested within a
+     * structure of data. For example, in order to `.push()` onto a nested `List`,
+     * `updateIn` and `push` can be used together:
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map, List } = require('immutable')
+     * const map = Map({ inMap: Map({ inList: List([ 1, 2, 3 ]) }) })
+     * const newMap = map.updateIn(['inMap', 'inList'], list => list.push(4))
+     * // Map { "inMap": Map { "inList": List [ 1, 2, 3, 4 ] } }
+     * ```
+     *
+     * If any keys in `keyPath` do not exist, new Immutable `Map`s will
+     * be created at those keys. If the `keyPath` does not already contain a
+     * value, the `updater` function will be called with `notSetValue`, if
+     * provided, otherwise `undefined`.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { Map } = require('immutable')" }
+     * -->
+     * ```js
+     * const map = Map({ a: Map({ b: Map({ c: 10 }) }) })
+     * const newMap = map.updateIn(['a', 'b', 'c'], val => val * 2)
+     * // Map { "a": Map { "b": Map { "c": 20 } } }
+     * ```
+     *
+     * If the `updater` function returns the same value it was called with, then
+     * no change will occur. This is still true if `notSetValue` is provided.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { Map } = require('immutable')" }
+     * -->
+     * ```js
+     * const map = Map({ a: Map({ b: Map({ c: 10 }) }) })
+     * const newMap = map.updateIn(['a', 'b', 'x'], 100, val => val)
+     * // Map { "a": Map { "b": Map { "c": 10 } } }
+     * assert.strictEqual(newMap, aMap)
+     * ```
+     *
+     * For code using ES2015 or later, using `notSetValue` is discourged in
+     * favor of function parameter default values. This helps to avoid any
+     * potential confusion with identify functions as described above.
+     *
+     * The previous example behaves differently when written with default values:
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { Map } = require('immutable')" }
+     * -->
+     * ```js
+     * const map = Map({ a: Map({ b: Map({ c: 10 }) }) })
+     * const newMap = map.updateIn(['a', 'b', 'x'], (val = 100) => val)
+     * // Map { "a": Map { "b": Map { "c": 10, "x": 100 } } }
+     * ```
+     *
+     * Plain JavaScript Object or Arrays may be nested within an Immutable.js
+     * Collection, and updateIn() can update those values as well, treating them
+     * immutably by creating new copies of those values with the changes applied.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { Map } = require('immutable')" }
+     * -->
+     * ```js
+     * const map = Map({ a: { b: { c: 10 } } })
+     * const newMap = map.updateIn(['a', 'b', 'c'], val => val * 2)
+     * // Map { "a": { b: { c: 20 } } }
+     * ```
+     *
+     * If any key in the path exists but cannot be updated (such as a primitive
+     * like number or a custom Object like Date), an error will be thrown.
+     *
+     * Note: `updateIn` can be used in `withMutations`.
+     */
+    updateIn(
+      keyPath: Iterable<unknown>,
+      notSetValue: unknown,
+      updater: (value: unknown) => unknown
+    ): this;
+    updateIn(
+      keyPath: Iterable<unknown>,
+      updater: (value: unknown) => unknown
+    ): this;
+
+    /**
+     * A combination of `updateIn` and `merge`, returning a new Map, but
+     * performing the merge at a point arrived at by following the keyPath.
+     * In other words, these two lines are equivalent:
+     *
+     * ```js
+     * map.updateIn(['a', 'b', 'c'], abc => abc.merge(y))
+     * map.mergeIn(['a', 'b', 'c'], y)
+     * ```
+     *
+     * Note: `mergeIn` can be used in `withMutations`.
+     */
+    mergeIn(keyPath: Iterable<unknown>, ...collections: Array<unknown>): this;
+
+    /**
+     * A combination of `updateIn` and `mergeDeep`, returning a new Map, but
+     * performing the deep merge at a point arrived at by following the keyPath.
+     * In other words, these two lines are equivalent:
+     *
+     * ```js
+     * map.updateIn(['a', 'b', 'c'], abc => abc.mergeDeep(y))
+     * map.mergeDeepIn(['a', 'b', 'c'], y)
+     * ```
+     *
+     * Note: `mergeDeepIn` can be used in `withMutations`.
+     */
+    mergeDeepIn(
+      keyPath: Iterable<unknown>,
+      ...collections: Array<unknown>
+    ): this;
+
+    // Transient changes
+
+    /**
+     * Every time you call one of the above functions, a new immutable Map is
+     * created. If a pure function calls a number of these to produce a final
+     * return value, then a penalty on performance and memory has been paid by
+     * creating all of the intermediate immutable Maps.
+     *
+     * If you need to apply a series of mutations to produce a new immutable
+     * Map, `withMutations()` creates a temporary mutable copy of the Map which
+     * can apply mutations in a highly performant manner. In fact, this is
+     * exactly how complex mutations like `merge` are done.
+     *
+     * As an example, this results in the creation of 2, not 4, new Maps:
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * const map1 = Map()
+     * const map2 = map1.withMutations(map => {
+     *   map.set('a', 1).set('b', 2).set('c', 3)
+     * })
+     * assert.equal(map1.size, 0)
+     * assert.equal(map2.size, 3)
+     * ```
+     *
+     * Note: Not all methods can be used on a mutable collection or within
+     * `withMutations`! Read the documentation for each method to see if it
+     * is safe to use in `withMutations`.
+     */
+    withMutations(mutator: (mutable: this) => unknown): this;
+
+    /**
+     * Another way to avoid creation of intermediate Immutable maps is to create
+     * a mutable copy of this collection. Mutable copies *always* return `this`,
+     * and thus shouldn't be used for equality. Your function should never return
+     * a mutable copy of a collection, only use it internally to create a new
+     * collection.
+     *
+     * If possible, use `withMutations` to work with temporary mutable copies as
+     * it provides an easier to use API and considers many common optimizations.
+     *
+     * Note: if the collection is already mutable, `asMutable` returns itself.
+     *
+     * Note: Not all methods can be used on a mutable collection or within
+     * `withMutations`! Read the documentation for each method to see if it
+     * is safe to use in `withMutations`.
+     *
+     * @see `Map#asImmutable`
+     */
+    asMutable(): this;
+
+    /**
+     * Returns true if this is a mutable copy (see `asMutable()`) and mutative
+     * alterations have been applied.
+     *
+     * @see `Map#asMutable`
+     */
+    wasAltered(): boolean;
+
+    /**
+     * The yin to `asMutable`'s yang. Because it applies to mutable collections,
+     * this operation is *mutable* and may return itself (though may not
+     * return itself, i.e. if the result is an empty collection). Once
+     * performed, the original mutable copy must no longer be mutated since it
+     * may be the immutable result.
+     *
+     * If possible, use `withMutations` to work with temporary mutable copies as
+     * it provides an easier to use API and considers many common optimizations.
+     *
+     * @see `Map#asMutable`
+     */
+    asImmutable(): this;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new Map with values passed through a
+     * `mapper` function.
+     *
+     *     Map({ a: 1, b: 2 }).map(x => 10 * x)
+     *     // Map { a: 10, b: 20 }
+     */
+    map<M>(
+      mapper: (value: V, key: K, iter: this) => M,
+      context?: unknown
+    ): Map<K, M>;
+
+    /**
+     * @see Collection.Keyed.mapKeys
+     */
+    mapKeys<M>(
+      mapper: (key: K, value: V, iter: this) => M,
+      context?: unknown
+    ): Map<M, V>;
+
+    /**
+     * @see Collection.Keyed.mapEntries
+     */
+    mapEntries<KM, VM>(
+      mapper: (
+        entry: [K, V],
+        index: number,
+        iter: this
+      ) => [KM, VM] | undefined,
+      context?: unknown
+    ): Map<KM, VM>;
+
+    /**
+     * Flat-maps the Map, returning a new Map.
+     *
+     * Similar to `data.map(...).flatten(true)`.
+     */
+    flatMap<KM, VM>(
+      mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+      context?: unknown
+    ): Map<KM, VM>;
+
+    /**
+     * Returns a new Map with only the entries for which the `predicate`
+     * function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends V>(
+      predicate: (value: V, key: K, iter: this) => value is F,
+      context?: unknown
+    ): Map<K, F>;
+    filter(
+      predicate: (value: V, key: K, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Map with the values for which the `predicate`
+     * function returns false and another for which is returns true.
+     */
+    partition<F extends V, C>(
+      predicate: (this: C, value: V, key: K, iter: this) => value is F,
+      context?: C
+    ): [Map<K, V>, Map<K, F>];
+    partition<C>(
+      predicate: (this: C, value: V, key: K, iter: this) => unknown,
+      context?: C
+    ): [this, this];
+
+    /**
+     * @see Collection.Keyed.flip
+     */
+    flip(): Map<V, K>;
+
+    /**
+     * Returns an OrderedMap of the same type which includes the same entries,
+     * stably sorted by using a `comparator`.
+     *
+     * If a `comparator` is not provided, a default comparator uses `<` and `>`.
+     *
+     * `comparator(valueA, valueB)`:
+     *
+     *   * Returns `0` if the elements should not be swapped.
+     *   * Returns `-1` (or any negative number) if `valueA` comes before `valueB`
+     *   * Returns `1` (or any positive number) if `valueA` comes after `valueB`
+     *   * Alternatively, can return a value of the `PairSorting` enum type
+     *   * Is pure, i.e. it must always return the same value for the same pair
+     *     of values.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * Map({ "c": 3, "a": 1, "b": 2 }).sort((a, b) => {
+     *   if (a < b) { return -1; }
+     *   if (a > b) { return 1; }
+     *   if (a === b) { return 0; }
+     * });
+     * // OrderedMap { "a": 1, "b": 2, "c": 3 }
+     * ```
+     *
+     * Note: `sort()` Always returns a new instance, even if the original was
+     * already sorted.
+     *
+     * Note: This is always an eager operation.
+     */
+    sort(comparator?: Comparator<V>): this & OrderedMap<K, V>;
+
+    /**
+     * Like `sort`, but also accepts a `comparatorValueMapper` which allows for
+     * sorting by more sophisticated means:
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * const beattles = Map({
+     *   John: { name: "Lennon" },
+     *   Paul: { name: "McCartney" },
+     *   George: { name: "Harrison" },
+     *   Ringo: { name: "Starr" },
+     * });
+     * beattles.sortBy(member => member.name);
+     * ```
+     *
+     * Note: `sortBy()` Always returns a new instance, even if the original was
+     * already sorted.
+     *
+     * Note: This is always an eager operation.
+     */
+    sortBy<C>(
+      comparatorValueMapper: (value: V, key: K, iter: this) => C,
+      comparator?: (valueA: C, valueB: C) => number
+    ): this & OrderedMap<K, V>;
+  }
+
+  /**
+   * A type of Map that has the additional guarantee that the iteration order of
+   * entries will be the order in which they were set().
+   *
+   * The iteration behavior of OrderedMap is the same as native ES6 Map and
+   * JavaScript Object.
+   *
+   * Note that `OrderedMap` are more expensive than non-ordered `Map` and may
+   * consume more memory. `OrderedMap#set` is amortized O(log32 N), but not
+   * stable.
+   */
+  namespace OrderedMap {
+    /**
+     * True if the provided value is an OrderedMap.
+     */
+    function isOrderedMap(
+      maybeOrderedMap: unknown
+    ): maybeOrderedMap is OrderedMap<unknown, unknown>;
+  }
+
+  /**
+   * Creates a new Immutable OrderedMap.
+   *
+   * Created with the same key value pairs as the provided Collection.Keyed or
+   * JavaScript Object or expects a Collection of [K, V] tuple entries.
+   *
+   * The iteration order of key-value pairs provided to this constructor will
+   * be preserved in the OrderedMap.
+   *
+   *     let newOrderedMap = OrderedMap({key: "value"})
+   *     let newOrderedMap = OrderedMap([["key", "value"]])
+   *
+   * Note: `OrderedMap` is a factory function and not a class, and does not use
+   * the `new` keyword during construction.
+   */
+  function OrderedMap<K, V>(collection?: Iterable<[K, V]>): OrderedMap<K, V>;
+  function OrderedMap<V>(obj: { [key: string]: V }): OrderedMap<string, V>;
+
+  interface OrderedMap<K, V> extends Map<K, V> {
+    /**
+     * The number of entries in this OrderedMap.
+     */
+    readonly size: number;
+
+    /**
+     * Returns a new OrderedMap also containing the new key, value pair. If an
+     * equivalent key already exists in this OrderedMap, it will be replaced
+     * while maintaining the existing order.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { OrderedMap } = require('immutable')
+     * const originalMap = OrderedMap({a:1, b:1, c:1})
+     * const updatedMap = originalMap.set('b', 2)
+     *
+     * originalMap
+     * // OrderedMap {a: 1, b: 1, c: 1}
+     * updatedMap
+     * // OrderedMap {a: 1, b: 2, c: 1}
+     * ```
+     *
+     * Note: `set` can be used in `withMutations`.
+     */
+    set(key: K, value: V): this;
+
+    /**
+     * Returns a new OrderedMap resulting from merging the provided Collections
+     * (or JS objects) into this OrderedMap. In other words, this takes each
+     * entry of each collection and sets it on this OrderedMap.
+     *
+     * Note: Values provided to `merge` are shallowly converted before being
+     * merged. No nested values are altered.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { OrderedMap } = require('immutable')
+     * const one = OrderedMap({ a: 10, b: 20, c: 30 })
+     * const two = OrderedMap({ b: 40, a: 50, d: 60 })
+     * one.merge(two) // OrderedMap { "a": 50, "b": 40, "c": 30, "d": 60 }
+     * two.merge(one) // OrderedMap { "b": 20, "a": 10, "d": 60, "c": 30 }
+     * ```
+     *
+     * Note: `merge` can be used in `withMutations`.
+     *
+     * @alias concat
+     */
+    merge<KC, VC>(
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): OrderedMap<K | KC, Exclude<V, VC> | VC>;
+    merge<C>(
+      ...collections: Array<{ [key: string]: C }>
+    ): OrderedMap<K | string, Exclude<V, C> | C>;
+
+    concat<KC, VC>(
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): OrderedMap<K | KC, Exclude<V, VC> | VC>;
+    concat<C>(
+      ...collections: Array<{ [key: string]: C }>
+    ): OrderedMap<K | string, Exclude<V, C> | C>;
+
+    mergeWith<KC, VC, VCC>(
+      merger: (oldVal: V, newVal: VC, key: K) => VCC,
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): OrderedMap<K | KC, V | VC | VCC>;
+    mergeWith<C, CC>(
+      merger: (oldVal: V, newVal: C, key: string) => CC,
+      ...collections: Array<{ [key: string]: C }>
+    ): OrderedMap<K | string, V | C | CC>;
+
+    mergeDeep<KC, VC>(
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): OrderedMap<K | KC, V | VC>;
+    mergeDeep<C>(
+      ...collections: Array<{ [key: string]: C }>
+    ): OrderedMap<K | string, V | C>;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new OrderedMap with values passed through a
+     * `mapper` function.
+     *
+     *     OrderedMap({ a: 1, b: 2 }).map(x => 10 * x)
+     *     // OrderedMap { "a": 10, "b": 20 }
+     *
+     * Note: `map()` always returns a new instance, even if it produced the same
+     * value at every step.
+     */
+    map<M>(
+      mapper: (value: V, key: K, iter: this) => M,
+      context?: unknown
+    ): OrderedMap<K, M>;
+
+    /**
+     * @see Collection.Keyed.mapKeys
+     */
+    mapKeys<M>(
+      mapper: (key: K, value: V, iter: this) => M,
+      context?: unknown
+    ): OrderedMap<M, V>;
+
+    /**
+     * @see Collection.Keyed.mapEntries
+     */
+    mapEntries<KM, VM>(
+      mapper: (
+        entry: [K, V],
+        index: number,
+        iter: this
+      ) => [KM, VM] | undefined,
+      context?: unknown
+    ): OrderedMap<KM, VM>;
+
+    /**
+     * Flat-maps the OrderedMap, returning a new OrderedMap.
+     *
+     * Similar to `data.map(...).flatten(true)`.
+     */
+    flatMap<KM, VM>(
+      mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+      context?: unknown
+    ): OrderedMap<KM, VM>;
+
+    /**
+     * Returns a new OrderedMap with only the entries for which the `predicate`
+     * function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends V>(
+      predicate: (value: V, key: K, iter: this) => value is F,
+      context?: unknown
+    ): OrderedMap<K, F>;
+    filter(
+      predicate: (value: V, key: K, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new OrderedMap with the values for which the `predicate`
+     * function returns false and another for which is returns true.
+     */
+    partition<F extends V, C>(
+      predicate: (this: C, value: V, key: K, iter: this) => value is F,
+      context?: C
+    ): [OrderedMap<K, V>, OrderedMap<K, F>];
+    partition<C>(
+      predicate: (this: C, value: V, key: K, iter: this) => unknown,
+      context?: C
+    ): [this, this];
+
+    /**
+     * @see Collection.Keyed.flip
+     */
+    flip(): OrderedMap<V, K>;
+  }
+
+  /**
+   * A Collection of unique values with `O(log32 N)` adds and has.
+   *
+   * When iterating a Set, the entries will be (value, value) pairs. Iteration
+   * order of a Set is undefined, however is stable. Multiple iterations of the
+   * same Set will iterate in the same order.
+   *
+   * Set values, like Map keys, may be of any type. Equality is determined using
+   * `Immutable.is`, enabling Sets to uniquely include other Immutable
+   * collections, custom value types, and NaN.
+   */
+  namespace Set {
+    /**
+     * True if the provided value is a Set
+     */
+    function isSet(maybeSet: unknown): maybeSet is Set<unknown>;
+
+    /**
+     * Creates a new Set containing `values`.
+     */
+    function of<T>(...values: Array<T>): Set<T>;
+
+    /**
+     * `Set.fromKeys()` creates a new immutable Set containing the keys from
+     * this Collection or JavaScript Object.
+     */
+    function fromKeys<T>(iter: Collection.Keyed<T, unknown>): Set<T>;
+    function fromKeys<T>(iter: Collection<T, unknown>): Set<T>;
+    function fromKeys(obj: { [key: string]: unknown }): Set<string>;
+
+    /**
+     * `Set.intersect()` creates a new immutable Set that is the intersection of
+     * a collection of other sets.
+     *
+     * ```js
+     * const { Set } = require('immutable')
+     * const intersected = Set.intersect([
+     *   Set([ 'a', 'b', 'c' ])
+     *   Set([ 'c', 'a', 't' ])
+     * ])
+     * // Set [ "a", "c" ]
+     * ```
+     */
+    function intersect<T>(sets: Iterable<Iterable<T>>): Set<T>;
+
+    /**
+     * `Set.union()` creates a new immutable Set that is the union of a
+     * collection of other sets.
+     *
+     * ```js
+     * const { Set } = require('immutable')
+     * const unioned = Set.union([
+     *   Set([ 'a', 'b', 'c' ])
+     *   Set([ 'c', 'a', 't' ])
+     * ])
+     * // Set [ "a", "b", "c", "t" ]
+     * ```
+     */
+    function union<T>(sets: Iterable<Iterable<T>>): Set<T>;
+  }
+
+  /**
+   * Create a new immutable Set containing the values of the provided
+   * collection-like.
+   *
+   * Note: `Set` is a factory function and not a class, and does not use the
+   * `new` keyword during construction.
+   */
+  function Set<T>(collection?: Iterable<T> | ArrayLike<T>): Set<T>;
+
+  interface Set<T> extends Collection.Set<T> {
+    /**
+     * The number of items in this Set.
+     */
+    readonly size: number;
+
+    // Persistent changes
+
+    /**
+     * Returns a new Set which also includes this value.
+     *
+     * Note: `add` can be used in `withMutations`.
+     */
+    add(value: T): this;
+
+    /**
+     * Returns a new Set which excludes this value.
+     *
+     * Note: `delete` can be used in `withMutations`.
+     *
+     * Note: `delete` **cannot** be safely used in IE8, use `remove` if
+     * supporting old browsers.
+     *
+     * @alias remove
+     */
+    delete(value: T): this;
+    remove(value: T): this;
+
+    /**
+     * Returns a new Set containing no values.
+     *
+     * Note: `clear` can be used in `withMutations`.
+     */
+    clear(): this;
+
+    /**
+     * Returns a Set including any value from `collections` that does not already
+     * exist in this Set.
+     *
+     * Note: `union` can be used in `withMutations`.
+     * @alias merge
+     * @alias concat
+     */
+    union<C>(...collections: Array<Iterable<C>>): Set<T | C>;
+    merge<C>(...collections: Array<Iterable<C>>): Set<T | C>;
+    concat<C>(...collections: Array<Iterable<C>>): Set<T | C>;
+
+    /**
+     * Returns a Set which has removed any values not also contained
+     * within `collections`.
+     *
+     * Note: `intersect` can be used in `withMutations`.
+     */
+    intersect(...collections: Array<Iterable<T>>): this;
+
+    /**
+     * Returns a Set excluding any values contained within `collections`.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { OrderedSet } = require('immutable')
+     * OrderedSet([ 1, 2, 3 ]).subtract([1, 3])
+     * // OrderedSet [2]
+     * ```
+     *
+     * Note: `subtract` can be used in `withMutations`.
+     */
+    subtract(...collections: Array<Iterable<T>>): this;
+
+    // Transient changes
+
+    /**
+     * Note: Not all methods can be used on a mutable collection or within
+     * `withMutations`! Check the documentation for each method to see if it
+     * mentions being safe to use in `withMutations`.
+     *
+     * @see `Map#withMutations`
+     */
+    withMutations(mutator: (mutable: this) => unknown): this;
+
+    /**
+     * Note: Not all methods can be used on a mutable collection or within
+     * `withMutations`! Check the documentation for each method to see if it
+     * mentions being safe to use in `withMutations`.
+     *
+     * @see `Map#asMutable`
+     */
+    asMutable(): this;
+
+    /**
+     * @see `Map#wasAltered`
+     */
+    wasAltered(): boolean;
+
+    /**
+     * @see `Map#asImmutable`
+     */
+    asImmutable(): this;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new Set with values passed through a
+     * `mapper` function.
+     *
+     *     Set([1,2]).map(x => 10 * x)
+     *     // Set [10,20]
+     */
+    map<M>(
+      mapper: (value: T, key: T, iter: this) => M,
+      context?: unknown
+    ): Set<M>;
+
+    /**
+     * Flat-maps the Set, returning a new Set.
+     *
+     * Similar to `set.map(...).flatten(true)`.
+     */
+    flatMap<M>(
+      mapper: (value: T, key: T, iter: this) => Iterable<M>,
+      context?: unknown
+    ): Set<M>;
+
+    /**
+     * Returns a new Set with only the values for which the `predicate`
+     * function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends T>(
+      predicate: (value: T, key: T, iter: this) => value is F,
+      context?: unknown
+    ): Set<F>;
+    filter(
+      predicate: (value: T, key: T, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Set with the values for which the `predicate` function
+     * returns false and another for which is returns true.
+     */
+    partition<F extends T, C>(
+      predicate: (this: C, value: T, key: T, iter: this) => value is F,
+      context?: C
+    ): [Set<T>, Set<F>];
+    partition<C>(
+      predicate: (this: C, value: T, key: T, iter: this) => unknown,
+      context?: C
+    ): [this, this];
+
+    /**
+     * Returns an OrderedSet of the same type which includes the same entries,
+     * stably sorted by using a `comparator`.
+     *
+     * If a `comparator` is not provided, a default comparator uses `<` and `>`.
+     *
+     * `comparator(valueA, valueB)`:
+     *
+     *   * Returns `0` if the elements should not be swapped.
+     *   * Returns `-1` (or any negative number) if `valueA` comes before `valueB`
+     *   * Returns `1` (or any positive number) if `valueA` comes after `valueB`
+     *   * Alternatively, can return a value of the `PairSorting` enum type
+     *   * Is pure, i.e. it must always return the same value for the same pair
+     *     of values.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Set } = require('immutable')
+     * Set(['b', 'a', 'c']).sort((a, b) => {
+     *   if (a < b) { return -1; }
+     *   if (a > b) { return 1; }
+     *   if (a === b) { return 0; }
+     * });
+     * // OrderedSet { "a":, "b", "c" }
+     * ```
+     *
+     * Note: `sort()` Always returns a new instance, even if the original was
+     * already sorted.
+     *
+     * Note: This is always an eager operation.
+     */
+    sort(comparator?: Comparator<T>): this & OrderedSet<T>;
+
+    /**
+     * Like `sort`, but also accepts a `comparatorValueMapper` which allows for
+     * sorting by more sophisticated means:
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Set } = require('immutable')
+     * const beattles = Set([
+     *   { name: "Lennon" },
+     *   { name: "McCartney" },
+     *   { name: "Harrison" },
+     *   { name: "Starr" },
+     * ]);
+     * beattles.sortBy(member => member.name);
+     * ```
+     *
+     * Note: `sortBy()` Always returns a new instance, even if the original was
+     * already sorted.
+     *
+     * Note: This is always an eager operation.
+     */
+    sortBy<C>(
+      comparatorValueMapper: (value: T, key: T, iter: this) => C,
+      comparator?: (valueA: C, valueB: C) => number
+    ): this & OrderedSet<T>;
+  }
+
+  /**
+   * A type of Set that has the additional guarantee that the iteration order of
+   * values will be the order in which they were `add`ed.
+   *
+   * The iteration behavior of OrderedSet is the same as native ES6 Set.
+   *
+   * Note that `OrderedSet` are more expensive than non-ordered `Set` and may
+   * consume more memory. `OrderedSet#add` is amortized O(log32 N), but not
+   * stable.
+   */
+  namespace OrderedSet {
+    /**
+     * True if the provided value is an OrderedSet.
+     */
+    function isOrderedSet(
+      maybeOrderedSet: unknown
+    ): maybeOrderedSet is OrderedSet<unknown>;
+
+    /**
+     * Creates a new OrderedSet containing `values`.
+     */
+    function of<T>(...values: Array<T>): OrderedSet<T>;
+
+    /**
+     * `OrderedSet.fromKeys()` creates a new immutable OrderedSet containing
+     * the keys from this Collection or JavaScript Object.
+     */
+    function fromKeys<T>(iter: Collection.Keyed<T, unknown>): OrderedSet<T>;
+    function fromKeys<T>(iter: Collection<T, unknown>): OrderedSet<T>;
+    function fromKeys(obj: { [key: string]: unknown }): OrderedSet<string>;
+  }
+
+  /**
+   * Create a new immutable OrderedSet containing the values of the provided
+   * collection-like.
+   *
+   * Note: `OrderedSet` is a factory function and not a class, and does not use
+   * the `new` keyword during construction.
+   */
+  function OrderedSet<T>(
+    collection?: Iterable<T> | ArrayLike<T>
+  ): OrderedSet<T>;
+
+  interface OrderedSet<T> extends Set<T> {
+    /**
+     * The number of items in this OrderedSet.
+     */
+    readonly size: number;
+
+    /**
+     * Returns an OrderedSet including any value from `collections` that does
+     * not already exist in this OrderedSet.
+     *
+     * Note: `union` can be used in `withMutations`.
+     * @alias merge
+     * @alias concat
+     */
+    union<C>(...collections: Array<Iterable<C>>): OrderedSet<T | C>;
+    merge<C>(...collections: Array<Iterable<C>>): OrderedSet<T | C>;
+    concat<C>(...collections: Array<Iterable<C>>): OrderedSet<T | C>;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new Set with values passed through a
+     * `mapper` function.
+     *
+     *     OrderedSet([ 1, 2 ]).map(x => 10 * x)
+     *     // OrderedSet [10, 20]
+     */
+    map<M>(
+      mapper: (value: T, key: T, iter: this) => M,
+      context?: unknown
+    ): OrderedSet<M>;
+
+    /**
+     * Flat-maps the OrderedSet, returning a new OrderedSet.
+     *
+     * Similar to `set.map(...).flatten(true)`.
+     */
+    flatMap<M>(
+      mapper: (value: T, key: T, iter: this) => Iterable<M>,
+      context?: unknown
+    ): OrderedSet<M>;
+
+    /**
+     * Returns a new OrderedSet with only the values for which the `predicate`
+     * function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends T>(
+      predicate: (value: T, key: T, iter: this) => value is F,
+      context?: unknown
+    ): OrderedSet<F>;
+    filter(
+      predicate: (value: T, key: T, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new OrderedSet with the values for which the `predicate`
+     * function returns false and another for which is returns true.
+     */
+    partition<F extends T, C>(
+      predicate: (this: C, value: T, key: T, iter: this) => value is F,
+      context?: C
+    ): [OrderedSet<T>, OrderedSet<F>];
+    partition<C>(
+      predicate: (this: C, value: T, key: T, iter: this) => unknown,
+      context?: C
+    ): [this, this];
+
+    /**
+     * Returns an OrderedSet of the same type "zipped" with the provided
+     * collections.
+     *
+     * Like `zipWith`, but using the default `zipper`: creating an `Array`.
+     *
+     * ```js
+     * const a = OrderedSet([ 1, 2, 3 ])
+     * const b = OrderedSet([ 4, 5, 6 ])
+     * const c = a.zip(b)
+     * // OrderedSet [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
+     * ```
+     */
+    zip<U>(other: Collection<unknown, U>): OrderedSet<[T, U]>;
+    zip<U, V>(
+      other1: Collection<unknown, U>,
+      other2: Collection<unknown, V>
+    ): OrderedSet<[T, U, V]>;
+    zip(
+      ...collections: Array<Collection<unknown, unknown>>
+    ): OrderedSet<unknown>;
+
+    /**
+     * Returns a OrderedSet of the same type "zipped" with the provided
+     * collections.
+     *
+     * Unlike `zip`, `zipAll` continues zipping until the longest collection is
+     * exhausted. Missing values from shorter collections are filled with `undefined`.
+     *
+     * ```js
+     * const a = OrderedSet([ 1, 2 ]);
+     * const b = OrderedSet([ 3, 4, 5 ]);
+     * const c = a.zipAll(b); // OrderedSet [ [ 1, 3 ], [ 2, 4 ], [ undefined, 5 ] ]
+     * ```
+     *
+     * Note: Since zipAll will return a collection as large as the largest
+     * input, some results may contain undefined values. TypeScript cannot
+     * account for these without cases (as of v2.5).
+     */
+    zipAll<U>(other: Collection<unknown, U>): OrderedSet<[T, U]>;
+    zipAll<U, V>(
+      other1: Collection<unknown, U>,
+      other2: Collection<unknown, V>
+    ): OrderedSet<[T, U, V]>;
+    zipAll(
+      ...collections: Array<Collection<unknown, unknown>>
+    ): OrderedSet<unknown>;
+
+    /**
+     * Returns an OrderedSet of the same type "zipped" with the provided
+     * collections by using a custom `zipper` function.
+     *
+     * @see Seq.Indexed.zipWith
+     */
+    zipWith<U, Z>(
+      zipper: (value: T, otherValue: U) => Z,
+      otherCollection: Collection<unknown, U>
+    ): OrderedSet<Z>;
+    zipWith<U, V, Z>(
+      zipper: (value: T, otherValue: U, thirdValue: V) => Z,
+      otherCollection: Collection<unknown, U>,
+      thirdCollection: Collection<unknown, V>
+    ): OrderedSet<Z>;
+    zipWith<Z>(
+      zipper: (...values: Array<unknown>) => Z,
+      ...collections: Array<Collection<unknown, unknown>>
+    ): OrderedSet<Z>;
+  }
+
+  /**
+   * Stacks are indexed collections which support very efficient O(1) addition
+   * and removal from the front using `unshift(v)` and `shift()`.
+   *
+   * For familiarity, Stack also provides `push(v)`, `pop()`, and `peek()`, but
+   * be aware that they also operate on the front of the list, unlike List or
+   * a JavaScript Array.
+   *
+   * Note: `reverse()` or any inherent reverse traversal (`reduceRight`,
+   * `lastIndexOf`, etc.) is not efficient with a Stack.
+   *
+   * Stack is implemented with a Single-Linked List.
+   */
+  namespace Stack {
+    /**
+     * True if the provided value is a Stack
+     */
+    function isStack(maybeStack: unknown): maybeStack is Stack<unknown>;
+
+    /**
+     * Creates a new Stack containing `values`.
+     */
+    function of<T>(...values: Array<T>): Stack<T>;
+  }
+
+  /**
+   * Create a new immutable Stack containing the values of the provided
+   * collection-like.
+   *
+   * The iteration order of the provided collection is preserved in the
+   * resulting `Stack`.
+   *
+   * Note: `Stack` is a factory function and not a class, and does not use the
+   * `new` keyword during construction.
+   */
+  function Stack<T>(collection?: Iterable<T> | ArrayLike<T>): Stack<T>;
+
+  interface Stack<T> extends Collection.Indexed<T> {
+    /**
+     * The number of items in this Stack.
+     */
+    readonly size: number;
+
+    // Reading values
+
+    /**
+     * Alias for `Stack.first()`.
+     */
+    peek(): T | undefined;
+
+    // Persistent changes
+
+    /**
+     * Returns a new Stack with 0 size and no values.
+     *
+     * Note: `clear` can be used in `withMutations`.
+     */
+    clear(): Stack<T>;
+
+    /**
+     * Returns a new Stack with the provided `values` prepended, shifting other
+     * values ahead to higher indices.
+     *
+     * This is very efficient for Stack.
+     *
+     * Note: `unshift` can be used in `withMutations`.
+     */
+    unshift(...values: Array<T>): Stack<T>;
+
+    /**
+     * Like `Stack#unshift`, but accepts a collection rather than varargs.
+     *
+     * Note: `unshiftAll` can be used in `withMutations`.
+     */
+    unshiftAll(iter: Iterable<T>): Stack<T>;
+
+    /**
+     * Returns a new Stack with a size ones less than this Stack, excluding
+     * the first item in this Stack, shifting all other values to a lower index.
+     *
+     * Note: this differs from `Array#shift` because it returns a new
+     * Stack rather than the removed value. Use `first()` or `peek()` to get the
+     * first value in this Stack.
+     *
+     * Note: `shift` can be used in `withMutations`.
+     */
+    shift(): Stack<T>;
+
+    /**
+     * Alias for `Stack#unshift` and is not equivalent to `List#push`.
+     */
+    push(...values: Array<T>): Stack<T>;
+
+    /**
+     * Alias for `Stack#unshiftAll`.
+     */
+    pushAll(iter: Iterable<T>): Stack<T>;
+
+    /**
+     * Alias for `Stack#shift` and is not equivalent to `List#pop`.
+     */
+    pop(): Stack<T>;
+
+    // Transient changes
+
+    /**
+     * Note: Not all methods can be used on a mutable collection or within
+     * `withMutations`! Check the documentation for each method to see if it
+     * mentions being safe to use in `withMutations`.
+     *
+     * @see `Map#withMutations`
+     */
+    withMutations(mutator: (mutable: this) => unknown): this;
+
+    /**
+     * Note: Not all methods can be used on a mutable collection or within
+     * `withMutations`! Check the documentation for each method to see if it
+     * mentions being safe to use in `withMutations`.
+     *
+     * @see `Map#asMutable`
+     */
+    asMutable(): this;
+
+    /**
+     * @see `Map#wasAltered`
+     */
+    wasAltered(): boolean;
+
+    /**
+     * @see `Map#asImmutable`
+     */
+    asImmutable(): this;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new Stack with other collections concatenated to this one.
+     */
+    concat<C>(...valuesOrCollections: Array<Iterable<C> | C>): Stack<T | C>;
+
+    /**
+     * Returns a new Stack with values passed through a
+     * `mapper` function.
+     *
+     *     Stack([ 1, 2 ]).map(x => 10 * x)
+     *     // Stack [ 10, 20 ]
+     *
+     * Note: `map()` always returns a new instance, even if it produced the same
+     * value at every step.
+     */
+    map<M>(
+      mapper: (value: T, key: number, iter: this) => M,
+      context?: unknown
+    ): Stack<M>;
+
+    /**
+     * Flat-maps the Stack, returning a new Stack.
+     *
+     * Similar to `stack.map(...).flatten(true)`.
+     */
+    flatMap<M>(
+      mapper: (value: T, key: number, iter: this) => Iterable<M>,
+      context?: unknown
+    ): Stack<M>;
+
+    /**
+     * Returns a new Set with only the values for which the `predicate`
+     * function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends T>(
+      predicate: (value: T, index: number, iter: this) => value is F,
+      context?: unknown
+    ): Set<F>;
+    filter(
+      predicate: (value: T, index: number, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a Stack "zipped" with the provided collections.
+     *
+     * Like `zipWith`, but using the default `zipper`: creating an `Array`.
+     *
+     * ```js
+     * const a = Stack([ 1, 2, 3 ]);
+     * const b = Stack([ 4, 5, 6 ]);
+     * const c = a.zip(b); // Stack [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
+     * ```
+     */
+    zip<U>(other: Collection<unknown, U>): Stack<[T, U]>;
+    zip<U, V>(
+      other: Collection<unknown, U>,
+      other2: Collection<unknown, V>
+    ): Stack<[T, U, V]>;
+    zip(...collections: Array<Collection<unknown, unknown>>): Stack<unknown>;
+
+    /**
+     * Returns a Stack "zipped" with the provided collections.
+     *
+     * Unlike `zip`, `zipAll` continues zipping until the longest collection is
+     * exhausted. Missing values from shorter collections are filled with `undefined`.
+     *
+     * ```js
+     * const a = Stack([ 1, 2 ]);
+     * const b = Stack([ 3, 4, 5 ]);
+     * const c = a.zipAll(b); // Stack [ [ 1, 3 ], [ 2, 4 ], [ undefined, 5 ] ]
+     * ```
+     *
+     * Note: Since zipAll will return a collection as large as the largest
+     * input, some results may contain undefined values. TypeScript cannot
+     * account for these without cases (as of v2.5).
+     */
+    zipAll<U>(other: Collection<unknown, U>): Stack<[T, U]>;
+    zipAll<U, V>(
+      other: Collection<unknown, U>,
+      other2: Collection<unknown, V>
+    ): Stack<[T, U, V]>;
+    zipAll(...collections: Array<Collection<unknown, unknown>>): Stack<unknown>;
+
+    /**
+     * Returns a Stack "zipped" with the provided collections by using a
+     * custom `zipper` function.
+     *
+     * ```js
+     * const a = Stack([ 1, 2, 3 ]);
+     * const b = Stack([ 4, 5, 6 ]);
+     * const c = a.zipWith((a, b) => a + b, b);
+     * // Stack [ 5, 7, 9 ]
+     * ```
+     */
+    zipWith<U, Z>(
+      zipper: (value: T, otherValue: U) => Z,
+      otherCollection: Collection<unknown, U>
+    ): Stack<Z>;
+    zipWith<U, V, Z>(
+      zipper: (value: T, otherValue: U, thirdValue: V) => Z,
+      otherCollection: Collection<unknown, U>,
+      thirdCollection: Collection<unknown, V>
+    ): Stack<Z>;
+    zipWith<Z>(
+      zipper: (...values: Array<unknown>) => Z,
+      ...collections: Array<Collection<unknown, unknown>>
+    ): Stack<Z>;
+  }
+
+  /**
+   * Returns a Seq.Indexed of numbers from `start` (inclusive) to `end`
+   * (exclusive), by `step`, where `start` defaults to 0, `step` to 1, and `end` to
+   * infinity. When `start` is equal to `end`, returns empty range.
+   *
+   * Note: `Range` is a factory function and not a class, and does not use the
+   * `new` keyword during construction.
+   *
+   * ```js
+   * const { Range } = require('immutable')
+   * Range() // [ 0, 1, 2, 3, ... ]
+   * Range(10) // [ 10, 11, 12, 13, ... ]
+   * Range(10, 15) // [ 10, 11, 12, 13, 14 ]
+   * Range(10, 30, 5) // [ 10, 15, 20, 25 ]
+   * Range(30, 10, 5) // [ 30, 25, 20, 15 ]
+   * Range(30, 30, 5) // []
+   * ```
+   */
+  function Range(
+    start: number,
+    end: number,
+    step?: number
+  ): Seq.Indexed<number>;
+
+  /**
+   * Returns a Seq.Indexed of `value` repeated `times` times. When `times` is
+   * not defined, returns an infinite `Seq` of `value`.
+   *
+   * Note: `Repeat` is a factory function and not a class, and does not use the
+   * `new` keyword during construction.
+   *
+   * ```js
+   * const { Repeat } = require('immutable')
+   * Repeat('foo') // [ 'foo', 'foo', 'foo', ... ]
+   * Repeat('bar', 4) // [ 'bar', 'bar', 'bar', 'bar' ]
+   * ```
+   */
+  function Repeat<T>(value: T, times?: number): Seq.Indexed<T>;
+
+  /**
+   * A record is similar to a JS object, but enforces a specific set of allowed
+   * string keys, and has default values.
+   *
+   * The `Record()` function produces new Record Factories, which when called
+   * create Record instances.
+   *
+   * ```js
+   * const { Record } = require('immutable')
+   * const ABRecord = Record({ a: 1, b: 2 })
+   * const myRecord = ABRecord({ b: 3 })
+   * ```
+   *
+   * Records always have a value for the keys they define. `remove`ing a key
+   * from a record simply resets it to the default value for that key.
+   *
+   * ```js
+   * myRecord.get('a') // 1
+   * myRecord.get('b') // 3
+   * const myRecordWithoutB = myRecord.remove('b')
+   * myRecordWithoutB.get('b') // 2
+   * ```
+   *
+   * Values provided to the constructor not found in the Record type will
+   * be ignored. For example, in this case, ABRecord is provided a key "x" even
+   * though only "a" and "b" have been defined. The value for "x" will be
+   * ignored for this record.
+   *
+   * ```js
+   * const myRecord = ABRecord({ b: 3, x: 10 })
+   * myRecord.get('x') // undefined
+   * ```
+   *
+   * Because Records have a known set of string keys, property get access works
+   * as expected, however property sets will throw an Error.
+   *
+   * Note: IE8 does not support property access. Only use `get()` when
+   * supporting IE8.
+   *
+   * ```js
+   * myRecord.b // 3
+   * myRecord.b = 5 // throws Error
+   * ```
+   *
+   * Record Types can be extended as well, allowing for custom methods on your
+   * Record. This is not a common pattern in functional environments, but is in
+   * many JS programs.
+   *
+   * However Record Types are more restricted than typical JavaScript classes.
+   * They do not use a class constructor, which also means they cannot use
+   * class properties (since those are technically part of a constructor).
+   *
+   * While Record Types can be syntactically created with the JavaScript `class`
+   * form, the resulting Record function is actually a factory function, not a
+   * class constructor. Even though Record Types are not classes, JavaScript
+   * currently requires the use of `new` when creating new Record instances if
+   * they are defined as a `class`.
+   *
+   * ```
+   * class ABRecord extends Record({ a: 1, b: 2 }) {
+   *   getAB() {
+   *     return this.a + this.b;
+   *   }
+   * }
+   *
+   * var myRecord = new ABRecord({b: 3})
+   * myRecord.getAB() // 4
+   * ```
+   *
+   *
+   * **Flow Typing Records:**
+   *
+   * Immutable.js exports two Flow types designed to make it easier to use
+   * Records with flow typed code, `RecordOf<TProps>` and `RecordFactory<TProps>`.
+   *
+   * When defining a new kind of Record factory function, use a flow type that
+   * describes the values the record contains along with `RecordFactory<TProps>`.
+   * To type instances of the Record (which the factory function returns),
+   * use `RecordOf<TProps>`.
+   *
+   * Typically, new Record definitions will export both the Record factory
+   * function as well as the Record instance type for use in other code.
+   *
+   * ```js
+   * import type { RecordFactory, RecordOf } from 'immutable';
+   *
+   * // Use RecordFactory<TProps> for defining new Record factory functions.
+   * type Point3DProps = { x: number, y: number, z: number };
+   * const defaultValues: Point3DProps = { x: 0, y: 0, z: 0 };
+   * const makePoint3D: RecordFactory<Point3DProps> = Record(defaultValues);
+   * export makePoint3D;
+   *
+   * // Use RecordOf<T> for defining new instances of that Record.
+   * export type Point3D = RecordOf<Point3DProps>;
+   * const some3DPoint: Point3D = makePoint3D({ x: 10, y: 20, z: 30 });
+   * ```
+   *
+   * **Flow Typing Record Subclasses:**
+   *
+   * Records can be subclassed as a means to add additional methods to Record
+   * instances. This is generally discouraged in favor of a more functional API,
+   * since Subclasses have some minor overhead. However the ability to create
+   * a rich API on Record types can be quite valuable.
+   *
+   * When using Flow to type Subclasses, do not use `RecordFactory<TProps>`,
+   * instead apply the props type when subclassing:
+   *
+   * ```js
+   * type PersonProps = {name: string, age: number};
+   * const defaultValues: PersonProps = {name: 'Aristotle', age: 2400};
+   * const PersonRecord = Record(defaultValues);
+   * class Person extends PersonRecord<PersonProps> {
+   *   getName(): string {
+   *     return this.get('name')
+   *   }
+   *
+   *   setName(name: string): this {
+   *     return this.set('name', name);
+   *   }
+   * }
+   * ```
+   *
+   * **Choosing Records vs plain JavaScript objects**
+   *
+   * Records offer a persistently immutable alternative to plain JavaScript
+   * objects, however they're not required to be used within Immutable.js
+   * collections. In fact, the deep-access and deep-updating functions
+   * like `getIn()` and `setIn()` work with plain JavaScript Objects as well.
+   *
+   * Deciding to use Records or Objects in your application should be informed
+   * by the tradeoffs and relative benefits of each:
+   *
+   * - *Runtime immutability*: plain JS objects may be carefully treated as
+   *   immutable, however Record instances will *throw* if attempted to be
+   *   mutated directly. Records provide this additional guarantee, however at
+   *   some marginal runtime cost. While JS objects are mutable by nature, the
+   *   use of type-checking tools like [Flow](https://medium.com/@gcanti/immutability-with-flow-faa050a1aef4)
+   *   can help gain confidence in code written to favor immutability.
+   *
+   * - *Value equality*: Records use value equality when compared with `is()`
+   *   or `record.equals()`. That is, two Records with the same keys and values
+   *   are equal. Plain objects use *reference equality*. Two objects with the
+   *   same keys and values are not equal since they are different objects.
+   *   This is important to consider when using objects as keys in a `Map` or
+   *   values in a `Set`, which use equality when retrieving values.
+   *
+   * - *API methods*: Records have a full featured API, with methods like
+   *   `.getIn()`, and `.equals()`. These can make working with these values
+   *   easier, but comes at the cost of not allowing keys with those names.
+   *
+   * - *Default values*: Records provide default values for every key, which
+   *   can be useful when constructing Records with often unchanging values.
+   *   However default values can make using Flow and TypeScript more laborious.
+   *
+   * - *Serialization*: Records use a custom internal representation to
+   *   efficiently store and update their values. Converting to and from this
+   *   form isn't free. If converting Records to plain objects is common,
+   *   consider sticking with plain objects to begin with.
+   */
+  namespace Record {
+    /**
+     * True if `maybeRecord` is an instance of a Record.
+     */
+    function isRecord(maybeRecord: unknown): maybeRecord is Record<{}>;
+
+    /**
+     * Records allow passing a second parameter to supply a descriptive name
+     * that appears when converting a Record to a string or in any error
+     * messages. A descriptive name for any record can be accessed by using this
+     * method. If one was not provided, the string "Record" is returned.
+     *
+     * ```js
+     * const { Record } = require('immutable')
+     * const Person = Record({
+     *   name: null
+     * }, 'Person')
+     *
+     * var me = Person({ name: 'My Name' })
+     * me.toString() // "Person { "name": "My Name" }"
+     * Record.getDescriptiveName(me) // "Person"
+     * ```
+     */
+    function getDescriptiveName(record: Record<any>): string;
+
+    /**
+     * A Record.Factory is created by the `Record()` function. Record instances
+     * are created by passing it some of the accepted values for that Record
+     * type:
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { Record } = require('immutable')" }
+     * -->
+     * ```js
+     * // makePerson is a Record Factory function
+     * const makePerson = Record({ name: null, favoriteColor: 'unknown' });
+     *
+     * // alan is a Record instance
+     * const alan = makePerson({ name: 'Alan' });
+     * ```
+     *
+     * Note that Record Factories return `Record<TProps> & Readonly<TProps>`,
+     * this allows use of both the Record instance API, and direct property
+     * access on the resulting instances:
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { Record } = require('immutable');const makePerson = Record({ name: null, favoriteColor: 'unknown' });const alan = makePerson({ name: 'Alan' });" }
+     * -->
+     * ```js
+     * // Use the Record API
+     * console.log('Record API: ' + alan.get('name'))
+     *
+     * // Or direct property access (Readonly)
+     * console.log('property access: ' + alan.name)
+     * ```
+     *
+     * **Flow Typing Records:**
+     *
+     * Use the `RecordFactory<TProps>` Flow type to get high quality type checking of
+     * Records:
+     *
+     * ```js
+     * import type { RecordFactory, RecordOf } from 'immutable';
+     *
+     * // Use RecordFactory<TProps> for defining new Record factory functions.
+     * type PersonProps = { name: ?string, favoriteColor: string };
+     * const makePerson: RecordFactory<PersonProps> = Record({ name: null, favoriteColor: 'unknown' });
+     *
+     * // Use RecordOf<T> for defining new instances of that Record.
+     * type Person = RecordOf<PersonProps>;
+     * const alan: Person = makePerson({ name: 'Alan' });
+     * ```
+     */
+    namespace Factory {}
+
+    interface Factory<TProps extends object> {
+      (values?: Partial<TProps> | Iterable<[string, unknown]>): Record<TProps> &
+        Readonly<TProps>;
+      new (
+        values?: Partial<TProps> | Iterable<[string, unknown]>
+      ): Record<TProps> & Readonly<TProps>;
+
+      /**
+       * The name provided to `Record(values, name)` can be accessed with
+       * `displayName`.
+       */
+      displayName: string;
+    }
+
+    function Factory<TProps extends object>(
+      values?: Partial<TProps> | Iterable<[string, unknown]>
+    ): Record<TProps> & Readonly<TProps>;
+  }
+
+  /**
+   * Unlike other types in Immutable.js, the `Record()` function creates a new
+   * Record Factory, which is a function that creates Record instances.
+   *
+   * See above for examples of using `Record()`.
+   *
+   * Note: `Record` is a factory function and not a class, and does not use the
+   * `new` keyword during construction.
+   */
+  function Record<TProps extends object>(
+    defaultValues: TProps,
+    name?: string
+  ): Record.Factory<TProps>;
+
+  interface Record<TProps extends object> {
+    // Reading values
+
+    has(key: string): key is keyof TProps & string;
+
+    /**
+     * Returns the value associated with the provided key, which may be the
+     * default value defined when creating the Record factory function.
+     *
+     * If the requested key is not defined by this Record type, then
+     * notSetValue will be returned if provided. Note that this scenario would
+     * produce an error when using Flow or TypeScript.
+     */
+    get<K extends keyof TProps>(key: K, notSetValue?: unknown): TProps[K];
+    get<T>(key: string, notSetValue: T): T;
+
+    // Reading deep values
+
+    hasIn(keyPath: Iterable<unknown>): boolean;
+    getIn(keyPath: Iterable<unknown>): unknown;
+
+    // Value equality
+
+    equals(other: unknown): boolean;
+    hashCode(): number;
+
+    // Persistent changes
+
+    set<K extends keyof TProps>(key: K, value: TProps[K]): this;
+    update<K extends keyof TProps>(
+      key: K,
+      updater: (value: TProps[K]) => TProps[K]
+    ): this;
+    merge(
+      ...collections: Array<Partial<TProps> | Iterable<[string, unknown]>>
+    ): this;
+    mergeDeep(
+      ...collections: Array<Partial<TProps> | Iterable<[string, unknown]>>
+    ): this;
+
+    mergeWith(
+      merger: (oldVal: unknown, newVal: unknown, key: keyof TProps) => unknown,
+      ...collections: Array<Partial<TProps> | Iterable<[string, unknown]>>
+    ): this;
+    mergeDeepWith(
+      merger: (oldVal: unknown, newVal: unknown, key: unknown) => unknown,
+      ...collections: Array<Partial<TProps> | Iterable<[string, unknown]>>
+    ): this;
+
+    /**
+     * Returns a new instance of this Record type with the value for the
+     * specific key set to its default value.
+     *
+     * @alias remove
+     */
+    delete<K extends keyof TProps>(key: K): this;
+    remove<K extends keyof TProps>(key: K): this;
+
+    /**
+     * Returns a new instance of this Record type with all values set
+     * to their default values.
+     */
+    clear(): this;
+
+    // Deep persistent changes
+
+    setIn(keyPath: Iterable<unknown>, value: unknown): this;
+    updateIn(
+      keyPath: Iterable<unknown>,
+      updater: (value: unknown) => unknown
+    ): this;
+    mergeIn(keyPath: Iterable<unknown>, ...collections: Array<unknown>): this;
+    mergeDeepIn(
+      keyPath: Iterable<unknown>,
+      ...collections: Array<unknown>
+    ): this;
+
+    /**
+     * @alias removeIn
+     */
+    deleteIn(keyPath: Iterable<unknown>): this;
+    removeIn(keyPath: Iterable<unknown>): this;
+
+    // Conversion to JavaScript types
+
+    /**
+     * Deeply converts this Record to equivalent native JavaScript Object.
+     *
+     * Note: This method may not be overridden. Objects with custom
+     * serialization to plain JS may override toJSON() instead.
+     */
+    toJS(): DeepCopy<TProps>;
+
+    /**
+     * Shallowly converts this Record to equivalent native JavaScript Object.
+     */
+    toJSON(): TProps;
+
+    /**
+     * Shallowly converts this Record to equivalent JavaScript Object.
+     */
+    toObject(): TProps;
+
+    // Transient changes
+
+    /**
+     * Note: Not all methods can be used on a mutable collection or within
+     * `withMutations`! Only `set` may be used mutatively.
+     *
+     * @see `Map#withMutations`
+     */
+    withMutations(mutator: (mutable: this) => unknown): this;
+
+    /**
+     * @see `Map#asMutable`
+     */
+    asMutable(): this;
+
+    /**
+     * @see `Map#wasAltered`
+     */
+    wasAltered(): boolean;
+
+    /**
+     * @see `Map#asImmutable`
+     */
+    asImmutable(): this;
+
+    // Sequence algorithms
+
+    toSeq(): Seq.Keyed<keyof TProps, TProps[keyof TProps]>;
+
+    [Symbol.iterator](): IterableIterator<[keyof TProps, TProps[keyof TProps]]>;
+  }
+
+  /**
+   * RecordOf<T> is used in TypeScript to define interfaces expecting an
+   * instance of record with type T.
+   *
+   * This is equivalent to an instance of a record created by a Record Factory.
+   */
+  type RecordOf<TProps extends object> = Record<TProps> & Readonly<TProps>;
+
+  /**
+   * `Seq` describes a lazy operation, allowing them to efficiently chain
+   * use of all the higher-order collection methods (such as `map` and `filter`)
+   * by not creating intermediate collections.
+   *
+   * **Seq is immutable** — Once a Seq is created, it cannot be
+   * changed, appended to, rearranged or otherwise modified. Instead, any
+   * mutative method called on a `Seq` will return a new `Seq`.
+   *
+   * **Seq is lazy** — `Seq` does as little work as necessary to respond to any
+   * method call. Values are often created during iteration, including implicit
+   * iteration when reducing or converting to a concrete data structure such as
+   * a `List` or JavaScript `Array`.
+   *
+   * For example, the following performs no work, because the resulting
+   * `Seq`'s values are never iterated:
+   *
+   * ```js
+   * const { Seq } = require('immutable')
+   * const oddSquares = Seq([ 1, 2, 3, 4, 5, 6, 7, 8 ])
+   *   .filter(x => x % 2 !== 0)
+   *   .map(x => x * x)
+   * ```
+   *
+   * Once the `Seq` is used, it performs only the work necessary. In this
+   * example, no intermediate arrays are ever created, filter is called three
+   * times, and map is only called once:
+   *
+   * ```js
+   * oddSquares.get(1); // 9
+   * ```
+   *
+   * Any collection can be converted to a lazy Seq with `Seq()`.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { Map } = require('immutable')
+   * const map = Map({ a: 1, b: 2, c: 3 })
+   * const lazySeq = Seq(map)
+   * ```
+   *
+   * `Seq` allows for the efficient chaining of operations, allowing for the
+   * expression of logic that can otherwise be very tedious:
+   *
+   * ```js
+   * lazySeq
+   *   .flip()
+   *   .map(key => key.toUpperCase())
+   *   .flip()
+   * // Seq { A: 1, B: 1, C: 1 }
+   * ```
+   *
+   * As well as expressing logic that would otherwise seem memory or time
+   * limited, for example `Range` is a special kind of Lazy sequence.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { Range } = require('immutable')
+   * Range(1, Infinity)
+   *   .skip(1000)
+   *   .map(n => -n)
+   *   .filter(n => n % 2 === 0)
+   *   .take(2)
+   *   .reduce((r, n) => r * n, 1)
+   * // 1006008
+   * ```
+   *
+   * Seq is often used to provide a rich collection API to JavaScript Object.
+   *
+   * ```js
+   * Seq({ x: 0, y: 1, z: 2 }).map(v => v * 2).toObject();
+   * // { x: 0, y: 2, z: 4 }
+   * ```
+   */
+
+  namespace Seq {
+    /**
+     * True if `maybeSeq` is a Seq, it is not backed by a concrete
+     * structure such as Map, List, or Set.
+     */
+    function isSeq(
+      maybeSeq: unknown
+    ): maybeSeq is
+      | Seq.Indexed<unknown>
+      | Seq.Keyed<unknown, unknown>
+      | Seq.Set<unknown>;
+
+    /**
+     * `Seq` which represents key-value pairs.
+     */
+    namespace Keyed {}
+
+    /**
+     * Always returns a Seq.Keyed, if input is not keyed, expects an
+     * collection of [K, V] tuples.
+     *
+     * Note: `Seq.Keyed` is a conversion function and not a class, and does not
+     * use the `new` keyword during construction.
+     */
+    function Keyed<K, V>(collection?: Iterable<[K, V]>): Seq.Keyed<K, V>;
+    function Keyed<V>(obj: { [key: string]: V }): Seq.Keyed<string, V>;
+
+    interface Keyed<K, V> extends Seq<K, V>, Collection.Keyed<K, V> {
+      /**
+       * Deeply converts this Keyed Seq to equivalent native JavaScript Object.
+       *
+       * Converts keys to Strings.
+       */
+      toJS(): { [key in string | number | symbol]: DeepCopy<V> };
+
+      /**
+       * Shallowly converts this Keyed Seq to equivalent native JavaScript Object.
+       *
+       * Converts keys to Strings.
+       */
+      toJSON(): { [key in string | number | symbol]: V };
+
+      /**
+       * Shallowly converts this collection to an Array.
+       */
+      toArray(): Array<[K, V]>;
+
+      /**
+       * Returns itself
+       */
+      toSeq(): this;
+
+      /**
+       * Returns a new Seq with other collections concatenated to this one.
+       *
+       * All entries will be present in the resulting Seq, even if they
+       * have the same key.
+       */
+      concat<KC, VC>(
+        ...collections: Array<Iterable<[KC, VC]>>
+      ): Seq.Keyed<K | KC, V | VC>;
+      concat<C>(
+        ...collections: Array<{ [key: string]: C }>
+      ): Seq.Keyed<K | string, V | C>;
+
+      /**
+       * Returns a new Seq.Keyed with values passed through a
+       * `mapper` function.
+       *
+       * ```js
+       * const { Seq } = require('immutable')
+       * Seq.Keyed({ a: 1, b: 2 }).map(x => 10 * x)
+       * // Seq { "a": 10, "b": 20 }
+       * ```
+       *
+       * Note: `map()` always returns a new instance, even if it produced the
+       * same value at every step.
+       */
+      map<M>(
+        mapper: (value: V, key: K, iter: this) => M,
+        context?: unknown
+      ): Seq.Keyed<K, M>;
+
+      /**
+       * @see Collection.Keyed.mapKeys
+       */
+      mapKeys<M>(
+        mapper: (key: K, value: V, iter: this) => M,
+        context?: unknown
+      ): Seq.Keyed<M, V>;
+
+      /**
+       * @see Collection.Keyed.mapEntries
+       */
+      mapEntries<KM, VM>(
+        mapper: (
+          entry: [K, V],
+          index: number,
+          iter: this
+        ) => [KM, VM] | undefined,
+        context?: unknown
+      ): Seq.Keyed<KM, VM>;
+
+      /**
+       * Flat-maps the Seq, returning a Seq of the same type.
+       *
+       * Similar to `seq.map(...).flatten(true)`.
+       */
+      flatMap<KM, VM>(
+        mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+        context?: unknown
+      ): Seq.Keyed<KM, VM>;
+
+      /**
+       * Returns a new Seq with only the entries for which the `predicate`
+       * function returns true.
+       *
+       * Note: `filter()` always returns a new instance, even if it results in
+       * not filtering out any values.
+       */
+      filter<F extends V>(
+        predicate: (value: V, key: K, iter: this) => value is F,
+        context?: unknown
+      ): Seq.Keyed<K, F>;
+      filter(
+        predicate: (value: V, key: K, iter: this) => unknown,
+        context?: unknown
+      ): this;
+
+      /**
+       * Returns a new keyed Seq with the values for which the `predicate`
+       * function returns false and another for which is returns true.
+       */
+      partition<F extends V, C>(
+        predicate: (this: C, value: V, key: K, iter: this) => value is F,
+        context?: C
+      ): [Seq.Keyed<K, V>, Seq.Keyed<K, F>];
+      partition<C>(
+        predicate: (this: C, value: V, key: K, iter: this) => unknown,
+        context?: C
+      ): [this, this];
+
+      /**
+       * @see Collection.Keyed.flip
+       */
+      flip(): Seq.Keyed<V, K>;
+
+      [Symbol.iterator](): IterableIterator<[K, V]>;
+    }
+
+    /**
+     * `Seq` which represents an ordered indexed list of values.
+     */
+    namespace Indexed {
+      /**
+       * Provides an Seq.Indexed of the values provided.
+       */
+      function of<T>(...values: Array<T>): Seq.Indexed<T>;
+    }
+
+    /**
+     * Always returns Seq.Indexed, discarding associated keys and
+     * supplying incrementing indices.
+     *
+     * Note: `Seq.Indexed` is a conversion function and not a class, and does
+     * not use the `new` keyword during construction.
+     */
+    function Indexed<T>(
+      collection?: Iterable<T> | ArrayLike<T>
+    ): Seq.Indexed<T>;
+
+    interface Indexed<T> extends Seq<number, T>, Collection.Indexed<T> {
+      /**
+       * Deeply converts this Indexed Seq to equivalent native JavaScript Array.
+       */
+      toJS(): Array<DeepCopy<T>>;
+
+      /**
+       * Shallowly converts this Indexed Seq to equivalent native JavaScript Array.
+       */
+      toJSON(): Array<T>;
+
+      /**
+       * Shallowly converts this collection to an Array.
+       */
+      toArray(): Array<T>;
+
+      /**
+       * Returns itself
+       */
+      toSeq(): this;
+
+      /**
+       * Returns a new Seq with other collections concatenated to this one.
+       */
+      concat<C>(
+        ...valuesOrCollections: Array<Iterable<C> | C>
+      ): Seq.Indexed<T | C>;
+
+      /**
+       * Returns a new Seq.Indexed with values passed through a
+       * `mapper` function.
+       *
+       * ```js
+       * const { Seq } = require('immutable')
+       * Seq.Indexed([ 1, 2 ]).map(x => 10 * x)
+       * // Seq [ 10, 20 ]
+       * ```
+       *
+       * Note: `map()` always returns a new instance, even if it produced the
+       * same value at every step.
+       */
+      map<M>(
+        mapper: (value: T, key: number, iter: this) => M,
+        context?: unknown
+      ): Seq.Indexed<M>;
+
+      /**
+       * Flat-maps the Seq, returning a a Seq of the same type.
+       *
+       * Similar to `seq.map(...).flatten(true)`.
+       */
+      flatMap<M>(
+        mapper: (value: T, key: number, iter: this) => Iterable<M>,
+        context?: unknown
+      ): Seq.Indexed<M>;
+
+      /**
+       * Returns a new Seq with only the values for which the `predicate`
+       * function returns true.
+       *
+       * Note: `filter()` always returns a new instance, even if it results in
+       * not filtering out any values.
+       */
+      filter<F extends T>(
+        predicate: (value: T, index: number, iter: this) => value is F,
+        context?: unknown
+      ): Seq.Indexed<F>;
+      filter(
+        predicate: (value: T, index: number, iter: this) => unknown,
+        context?: unknown
+      ): this;
+
+      /**
+       * Returns a new indexed Seq with the values for which the `predicate`
+       * function returns false and another for which is returns true.
+       */
+      partition<F extends T, C>(
+        predicate: (this: C, value: T, index: number, iter: this) => value is F,
+        context?: C
+      ): [Seq.Indexed<T>, Seq.Indexed<F>];
+      partition<C>(
+        predicate: (this: C, value: T, index: number, iter: this) => unknown,
+        context?: C
+      ): [this, this];
+
+      /**
+       * Returns a Seq "zipped" with the provided collections.
+       *
+       * Like `zipWith`, but using the default `zipper`: creating an `Array`.
+       *
+       * ```js
+       * const a = Seq([ 1, 2, 3 ]);
+       * const b = Seq([ 4, 5, 6 ]);
+       * const c = a.zip(b); // Seq [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
+       * ```
+       */
+      zip<U>(other: Collection<unknown, U>): Seq.Indexed<[T, U]>;
+      zip<U, V>(
+        other: Collection<unknown, U>,
+        other2: Collection<unknown, V>
+      ): Seq.Indexed<[T, U, V]>;
+      zip(
+        ...collections: Array<Collection<unknown, unknown>>
+      ): Seq.Indexed<unknown>;
+
+      /**
+       * Returns a Seq "zipped" with the provided collections.
+       *
+       * Unlike `zip`, `zipAll` continues zipping until the longest collection is
+       * exhausted. Missing values from shorter collections are filled with `undefined`.
+       *
+       * ```js
+       * const a = Seq([ 1, 2 ]);
+       * const b = Seq([ 3, 4, 5 ]);
+       * const c = a.zipAll(b); // Seq [ [ 1, 3 ], [ 2, 4 ], [ undefined, 5 ] ]
+       * ```
+       */
+      zipAll<U>(other: Collection<unknown, U>): Seq.Indexed<[T, U]>;
+      zipAll<U, V>(
+        other: Collection<unknown, U>,
+        other2: Collection<unknown, V>
+      ): Seq.Indexed<[T, U, V]>;
+      zipAll(
+        ...collections: Array<Collection<unknown, unknown>>
+      ): Seq.Indexed<unknown>;
+
+      /**
+       * Returns a Seq "zipped" with the provided collections by using a
+       * custom `zipper` function.
+       *
+       * ```js
+       * const a = Seq([ 1, 2, 3 ]);
+       * const b = Seq([ 4, 5, 6 ]);
+       * const c = a.zipWith((a, b) => a + b, b);
+       * // Seq [ 5, 7, 9 ]
+       * ```
+       */
+      zipWith<U, Z>(
+        zipper: (value: T, otherValue: U) => Z,
+        otherCollection: Collection<unknown, U>
+      ): Seq.Indexed<Z>;
+      zipWith<U, V, Z>(
+        zipper: (value: T, otherValue: U, thirdValue: V) => Z,
+        otherCollection: Collection<unknown, U>,
+        thirdCollection: Collection<unknown, V>
+      ): Seq.Indexed<Z>;
+      zipWith<Z>(
+        zipper: (...values: Array<unknown>) => Z,
+        ...collections: Array<Collection<unknown, unknown>>
+      ): Seq.Indexed<Z>;
+
+      [Symbol.iterator](): IterableIterator<T>;
+    }
+
+    /**
+     * `Seq` which represents a set of values.
+     *
+     * Because `Seq` are often lazy, `Seq.Set` does not provide the same guarantee
+     * of value uniqueness as the concrete `Set`.
+     */
+    namespace Set {
+      /**
+       * Returns a Seq.Set of the provided values
+       */
+      function of<T>(...values: Array<T>): Seq.Set<T>;
+    }
+
+    /**
+     * Always returns a Seq.Set, discarding associated indices or keys.
+     *
+     * Note: `Seq.Set` is a conversion function and not a class, and does not
+     * use the `new` keyword during construction.
+     */
+    function Set<T>(collection?: Iterable<T> | ArrayLike<T>): Seq.Set<T>;
+
+    interface Set<T> extends Seq<T, T>, Collection.Set<T> {
+      /**
+       * Deeply converts this Set Seq to equivalent native JavaScript Array.
+       */
+      toJS(): Array<DeepCopy<T>>;
+
+      /**
+       * Shallowly converts this Set Seq to equivalent native JavaScript Array.
+       */
+      toJSON(): Array<T>;
+
+      /**
+       * Shallowly converts this collection to an Array.
+       */
+      toArray(): Array<T>;
+
+      /**
+       * Returns itself
+       */
+      toSeq(): this;
+
+      /**
+       * Returns a new Seq with other collections concatenated to this one.
+       *
+       * All entries will be present in the resulting Seq, even if they
+       * are duplicates.
+       */
+      concat<U>(...collections: Array<Iterable<U>>): Seq.Set<T | U>;
+
+      /**
+       * Returns a new Seq.Set with values passed through a
+       * `mapper` function.
+       *
+       * ```js
+       * Seq.Set([ 1, 2 ]).map(x => 10 * x)
+       * // Seq { 10, 20 }
+       * ```
+       *
+       * Note: `map()` always returns a new instance, even if it produced the
+       * same value at every step.
+       */
+      map<M>(
+        mapper: (value: T, key: T, iter: this) => M,
+        context?: unknown
+      ): Seq.Set<M>;
+
+      /**
+       * Flat-maps the Seq, returning a Seq of the same type.
+       *
+       * Similar to `seq.map(...).flatten(true)`.
+       */
+      flatMap<M>(
+        mapper: (value: T, key: T, iter: this) => Iterable<M>,
+        context?: unknown
+      ): Seq.Set<M>;
+
+      /**
+       * Returns a new Seq with only the values for which the `predicate`
+       * function returns true.
+       *
+       * Note: `filter()` always returns a new instance, even if it results in
+       * not filtering out any values.
+       */
+      filter<F extends T>(
+        predicate: (value: T, key: T, iter: this) => value is F,
+        context?: unknown
+      ): Seq.Set<F>;
+      filter(
+        predicate: (value: T, key: T, iter: this) => unknown,
+        context?: unknown
+      ): this;
+
+      /**
+       * Returns a new set Seq with the values for which the `predicate`
+       * function returns false and another for which is returns true.
+       */
+      partition<F extends T, C>(
+        predicate: (this: C, value: T, key: T, iter: this) => value is F,
+        context?: C
+      ): [Seq.Set<T>, Seq.Set<F>];
+      partition<C>(
+        predicate: (this: C, value: T, key: T, iter: this) => unknown,
+        context?: C
+      ): [this, this];
+
+      [Symbol.iterator](): IterableIterator<T>;
+    }
+  }
+
+  /**
+   * Creates a Seq.
+   *
+   * Returns a particular kind of `Seq` based on the input.
+   *
+   *   * If a `Seq`, that same `Seq`.
+   *   * If an `Collection`, a `Seq` of the same kind (Keyed, Indexed, or Set).
+   *   * If an Array-like, an `Seq.Indexed`.
+   *   * If an Iterable Object, an `Seq.Indexed`.
+   *   * If an Object, a `Seq.Keyed`.
+   *
+   * Note: An Iterator itself will be treated as an object, becoming a `Seq.Keyed`,
+   * which is usually not what you want. You should turn your Iterator Object into
+   * an iterable object by defining a Symbol.iterator (or @@iterator) method which
+   * returns `this`.
+   *
+   * Note: `Seq` is a conversion function and not a class, and does not use the
+   * `new` keyword during construction.
+   */
+  function Seq<S extends Seq<unknown, unknown>>(seq: S): S;
+  function Seq<K, V>(collection: Collection.Keyed<K, V>): Seq.Keyed<K, V>;
+  function Seq<T>(collection: Collection.Set<T>): Seq.Set<T>;
+  function Seq<T>(
+    collection: Collection.Indexed<T> | Iterable<T> | ArrayLike<T>
+  ): Seq.Indexed<T>;
+  function Seq<V>(obj: { [key: string]: V }): Seq.Keyed<string, V>;
+  function Seq<K = unknown, V = unknown>(): Seq<K, V>;
+
+  interface Seq<K, V> extends Collection<K, V> {
+    /**
+     * Some Seqs can describe their size lazily. When this is the case,
+     * size will be an integer. Otherwise it will be undefined.
+     *
+     * For example, Seqs returned from `map()` or `reverse()`
+     * preserve the size of the original `Seq` while `filter()` does not.
+     *
+     * Note: `Range`, `Repeat` and `Seq`s made from `Array`s and `Object`s will
+     * always have a size.
+     */
+    readonly size: number | undefined;
+
+    // Force evaluation
+
+    /**
+     * Because Sequences are lazy and designed to be chained together, they do
+     * not cache their results. For example, this map function is called a total
+     * of 6 times, as each `join` iterates the Seq of three values.
+     *
+     *     var squares = Seq([ 1, 2, 3 ]).map(x => x * x)
+     *     squares.join() + squares.join()
+     *
+     * If you know a `Seq` will be used multiple times, it may be more
+     * efficient to first cache it in memory. Here, the map function is called
+     * only 3 times.
+     *
+     *     var squares = Seq([ 1, 2, 3 ]).map(x => x * x).cacheResult()
+     *     squares.join() + squares.join()
+     *
+     * Use this method judiciously, as it must fully evaluate a Seq which can be
+     * a burden on memory and possibly performance.
+     *
+     * Note: after calling `cacheResult`, a Seq will always have a `size`.
+     */
+    cacheResult(): this;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new Seq with values passed through a
+     * `mapper` function.
+     *
+     * ```js
+     * const { Seq } = require('immutable')
+     * Seq([ 1, 2 ]).map(x => 10 * x)
+     * // Seq [ 10, 20 ]
+     * ```
+     *
+     * Note: `map()` always returns a new instance, even if it produced the same
+     * value at every step.
+     */
+    map<M>(
+      mapper: (value: V, key: K, iter: this) => M,
+      context?: unknown
+    ): Seq<K, M>;
+
+    /**
+     * Returns a new Seq with values passed through a
+     * `mapper` function.
+     *
+     * ```js
+     * const { Seq } = require('immutable')
+     * Seq([ 1, 2 ]).map(x => 10 * x)
+     * // Seq [ 10, 20 ]
+     * ```
+     *
+     * Note: `map()` always returns a new instance, even if it produced the same
+     * value at every step.
+     * Note: used only for sets.
+     */
+    map<M>(
+      mapper: (value: V, key: K, iter: this) => M,
+      context?: unknown
+    ): Seq<M, M>;
+
+    /**
+     * Flat-maps the Seq, returning a Seq of the same type.
+     *
+     * Similar to `seq.map(...).flatten(true)`.
+     */
+    flatMap<M>(
+      mapper: (value: V, key: K, iter: this) => Iterable<M>,
+      context?: unknown
+    ): Seq<K, M>;
+
+    /**
+     * Flat-maps the Seq, returning a Seq of the same type.
+     *
+     * Similar to `seq.map(...).flatten(true)`.
+     * Note: Used only for sets.
+     */
+    flatMap<M>(
+      mapper: (value: V, key: K, iter: this) => Iterable<M>,
+      context?: unknown
+    ): Seq<M, M>;
+
+    /**
+     * Returns a new Seq with only the values for which the `predicate`
+     * function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends V>(
+      predicate: (value: V, key: K, iter: this) => value is F,
+      context?: unknown
+    ): Seq<K, F>;
+    filter(
+      predicate: (value: V, key: K, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Seq with the values for which the `predicate` function
+     * returns false and another for which is returns true.
+     */
+    partition<F extends V, C>(
+      predicate: (this: C, value: V, key: K, iter: this) => value is F,
+      context?: C
+    ): [Seq<K, V>, Seq<K, F>];
+    partition<C>(
+      predicate: (this: C, value: V, key: K, iter: this) => unknown,
+      context?: C
+    ): [this, this];
+  }
+
+  /**
+   * The `Collection` is a set of (key, value) entries which can be iterated, and
+   * is the base class for all collections in `immutable`, allowing them to
+   * make use of all the Collection methods (such as `map` and `filter`).
+   *
+   * Note: A collection is always iterated in the same order, however that order
+   * may not always be well defined, as is the case for the `Map` and `Set`.
+   *
+   * Collection is the abstract base class for concrete data structures. It
+   * cannot be constructed directly.
+   *
+   * Implementations should extend one of the subclasses, `Collection.Keyed`,
+   * `Collection.Indexed`, or `Collection.Set`.
+   */
+  namespace Collection {
+    /**
+     * Keyed Collections have discrete keys tied to each value.
+     *
+     * When iterating `Collection.Keyed`, each iteration will yield a `[K, V]`
+     * tuple, in other words, `Collection#entries` is the default iterator for
+     * Keyed Collections.
+     */
+    namespace Keyed {}
+
+    /**
+     * Creates a Collection.Keyed
+     *
+     * Similar to `Collection()`, however it expects collection-likes of [K, V]
+     * tuples if not constructed from a Collection.Keyed or JS Object.
+     *
+     * Note: `Collection.Keyed` is a conversion function and not a class, and
+     * does not use the `new` keyword during construction.
+     */
+    function Keyed<K, V>(collection?: Iterable<[K, V]>): Collection.Keyed<K, V>;
+    function Keyed<V>(obj: { [key: string]: V }): Collection.Keyed<string, V>;
+
+    interface Keyed<K, V> extends Collection<K, V> {
+      /**
+       * Deeply converts this Keyed collection to equivalent native JavaScript Object.
+       *
+       * Converts keys to Strings.
+       */
+      toJS(): { [key in string | number | symbol]: DeepCopy<V> };
+
+      /**
+       * Shallowly converts this Keyed collection to equivalent native JavaScript Object.
+       *
+       * Converts keys to Strings.
+       */
+      toJSON(): { [key in string | number | symbol]: V };
+
+      /**
+       * Shallowly converts this collection to an Array.
+       */
+      toArray(): Array<[K, V]>;
+
+      /**
+       * Returns Seq.Keyed.
+       * @override
+       */
+      toSeq(): Seq.Keyed<K, V>;
+
+      // Sequence functions
+
+      /**
+       * Returns a new Collection.Keyed of the same type where the keys and values
+       * have been flipped.
+       *
+       * <!-- runkit:activate -->
+       * ```js
+       * const { Map } = require('immutable')
+       * Map({ a: 'z', b: 'y' }).flip()
+       * // Map { "z": "a", "y": "b" }
+       * ```
+       */
+      flip(): Collection.Keyed<V, K>;
+
+      /**
+       * Returns a new Collection with other collections concatenated to this one.
+       */
+      concat<KC, VC>(
+        ...collections: Array<Iterable<[KC, VC]>>
+      ): Collection.Keyed<K | KC, V | VC>;
+      concat<C>(
+        ...collections: Array<{ [key: string]: C }>
+      ): Collection.Keyed<K | string, V | C>;
+
+      /**
+       * Returns a new Collection.Keyed with values passed through a
+       * `mapper` function.
+       *
+       * ```js
+       * const { Collection } = require('immutable')
+       * Collection.Keyed({ a: 1, b: 2 }).map(x => 10 * x)
+       * // Seq { "a": 10, "b": 20 }
+       * ```
+       *
+       * Note: `map()` always returns a new instance, even if it produced the
+       * same value at every step.
+       */
+      map<M>(
+        mapper: (value: V, key: K, iter: this) => M,
+        context?: unknown
+      ): Collection.Keyed<K, M>;
+
+      /**
+       * Returns a new Collection.Keyed of the same type with keys passed through
+       * a `mapper` function.
+       *
+       * <!-- runkit:activate -->
+       * ```js
+       * const { Map } = require('immutable')
+       * Map({ a: 1, b: 2 }).mapKeys(x => x.toUpperCase())
+       * // Map { "A": 1, "B": 2 }
+       * ```
+       *
+       * Note: `mapKeys()` always returns a new instance, even if it produced
+       * the same key at every step.
+       */
+      mapKeys<M>(
+        mapper: (key: K, value: V, iter: this) => M,
+        context?: unknown
+      ): Collection.Keyed<M, V>;
+
+      /**
+       * Returns a new Collection.Keyed of the same type with entries
+       * ([key, value] tuples) passed through a `mapper` function.
+       *
+       * <!-- runkit:activate -->
+       * ```js
+       * const { Map } = require('immutable')
+       * Map({ a: 1, b: 2 })
+       *   .mapEntries(([ k, v ]) => [ k.toUpperCase(), v * 2 ])
+       * // Map { "A": 2, "B": 4 }
+       * ```
+       *
+       * Note: `mapEntries()` always returns a new instance, even if it produced
+       * the same entry at every step.
+       *
+       * If the mapper function returns `undefined`, then the entry will be filtered
+       */
+      mapEntries<KM, VM>(
+        mapper: (
+          entry: [K, V],
+          index: number,
+          iter: this
+        ) => [KM, VM] | undefined,
+        context?: unknown
+      ): Collection.Keyed<KM, VM>;
+
+      /**
+       * Flat-maps the Collection, returning a Collection of the same type.
+       *
+       * Similar to `collection.map(...).flatten(true)`.
+       */
+      flatMap<KM, VM>(
+        mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+        context?: unknown
+      ): Collection.Keyed<KM, VM>;
+
+      /**
+       * Returns a new Collection with only the values for which the `predicate`
+       * function returns true.
+       *
+       * Note: `filter()` always returns a new instance, even if it results in
+       * not filtering out any values.
+       */
+      filter<F extends V>(
+        predicate: (value: V, key: K, iter: this) => value is F,
+        context?: unknown
+      ): Collection.Keyed<K, F>;
+      filter(
+        predicate: (value: V, key: K, iter: this) => unknown,
+        context?: unknown
+      ): this;
+
+      /**
+       * Returns a new keyed Collection with the values for which the
+       * `predicate` function returns false and another for which is returns
+       * true.
+       */
+      partition<F extends V, C>(
+        predicate: (this: C, value: V, key: K, iter: this) => value is F,
+        context?: C
+      ): [Collection.Keyed<K, V>, Collection.Keyed<K, F>];
+      partition<C>(
+        predicate: (this: C, value: V, key: K, iter: this) => unknown,
+        context?: C
+      ): [this, this];
+
+      [Symbol.iterator](): IterableIterator<[K, V]>;
+    }
+
+    /**
+     * Indexed Collections have incrementing numeric keys. They exhibit
+     * slightly different behavior than `Collection.Keyed` for some methods in order
+     * to better mirror the behavior of JavaScript's `Array`, and add methods
+     * which do not make sense on non-indexed Collections such as `indexOf`.
+     *
+     * Unlike JavaScript arrays, `Collection.Indexed`s are always dense. "Unset"
+     * indices and `undefined` indices are indistinguishable, and all indices from
+     * 0 to `size` are visited when iterated.
+     *
+     * All Collection.Indexed methods return re-indexed Collections. In other words,
+     * indices always start at 0 and increment until size. If you wish to
+     * preserve indices, using them as keys, convert to a Collection.Keyed by
+     * calling `toKeyedSeq`.
+     */
+    namespace Indexed {}
+
+    /**
+     * Creates a new Collection.Indexed.
+     *
+     * Note: `Collection.Indexed` is a conversion function and not a class, and
+     * does not use the `new` keyword during construction.
+     */
+    function Indexed<T>(
+      collection?: Iterable<T> | ArrayLike<T>
+    ): Collection.Indexed<T>;
+
+    interface Indexed<T> extends Collection<number, T> {
+      /**
+       * Deeply converts this Indexed collection to equivalent native JavaScript Array.
+       */
+      toJS(): Array<DeepCopy<T>>;
+
+      /**
+       * Shallowly converts this Indexed collection to equivalent native JavaScript Array.
+       */
+      toJSON(): Array<T>;
+
+      /**
+       * Shallowly converts this collection to an Array.
+       */
+      toArray(): Array<T>;
+
+      // Reading values
+
+      /**
+       * Returns the value associated with the provided index, or notSetValue if
+       * the index is beyond the bounds of the Collection.
+       *
+       * `index` may be a negative number, which indexes back from the end of the
+       * Collection. `s.get(-1)` gets the last item in the Collection.
+       */
+      get<NSV>(index: number, notSetValue: NSV): T | NSV;
+      get(index: number): T | undefined;
+
+      // Conversion to Seq
+
+      /**
+       * Returns Seq.Indexed.
+       * @override
+       */
+      toSeq(): Seq.Indexed<T>;
+
+      /**
+       * If this is a collection of [key, value] entry tuples, it will return a
+       * Seq.Keyed of those entries.
+       */
+      fromEntrySeq(): Seq.Keyed<unknown, unknown>;
+
+      // Combination
+
+      /**
+       * Returns a Collection of the same type with `separator` between each item
+       * in this Collection.
+       */
+      interpose(separator: T): this;
+
+      /**
+       * Returns a Collection of the same type with the provided `collections`
+       * interleaved into this collection.
+       *
+       * The resulting Collection includes the first item from each, then the
+       * second from each, etc.
+       *
+       * <!-- runkit:activate
+       *      { "preamble": "require('immutable')"}
+       * -->
+       * ```js
+       * const { List } = require('immutable')
+       * List([ 1, 2, 3 ]).interleave(List([ 'A', 'B', 'C' ]))
+       * // List [ 1, "A", 2, "B", 3, "C" ]
+       * ```
+       *
+       * The shortest Collection stops interleave.
+       *
+       * <!-- runkit:activate
+       *      { "preamble": "const { List } = require('immutable')" }
+       * -->
+       * ```js
+       * List([ 1, 2, 3 ]).interleave(
+       *   List([ 'A', 'B' ]),
+       *   List([ 'X', 'Y', 'Z' ])
+       * )
+       * // List [ 1, "A", "X", 2, "B", "Y" ]
+       * ```
+       *
+       * Since `interleave()` re-indexes values, it produces a complete copy,
+       * which has `O(N)` complexity.
+       *
+       * Note: `interleave` *cannot* be used in `withMutations`.
+       */
+      interleave(...collections: Array<Collection<unknown, T>>): this;
+
+      /**
+       * Splice returns a new indexed Collection by replacing a region of this
+       * Collection with new values. If values are not provided, it only skips the
+       * region to be removed.
+       *
+       * `index` may be a negative number, which indexes back from the end of the
+       * Collection. `s.splice(-2)` splices after the second to last item.
+       *
+       * <!-- runkit:activate -->
+       * ```js
+       * const { List } = require('immutable')
+       * List([ 'a', 'b', 'c', 'd' ]).splice(1, 2, 'q', 'r', 's')
+       * // List [ "a", "q", "r", "s", "d" ]
+       * ```
+       *
+       * Since `splice()` re-indexes values, it produces a complete copy, which
+       * has `O(N)` complexity.
+       *
+       * Note: `splice` *cannot* be used in `withMutations`.
+       */
+      splice(index: number, removeNum: number, ...values: Array<T>): this;
+
+      /**
+       * Returns a Collection of the same type "zipped" with the provided
+       * collections.
+       *
+       * Like `zipWith`, but using the default `zipper`: creating an `Array`.
+       *
+       *
+       * <!-- runkit:activate
+       *      { "preamble": "const { List } = require('immutable')" }
+       * -->
+       * ```js
+       * const a = List([ 1, 2, 3 ]);
+       * const b = List([ 4, 5, 6 ]);
+       * const c = a.zip(b); // List [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
+       * ```
+       */
+      zip<U>(other: Collection<unknown, U>): Collection.Indexed<[T, U]>;
+      zip<U, V>(
+        other: Collection<unknown, U>,
+        other2: Collection<unknown, V>
+      ): Collection.Indexed<[T, U, V]>;
+      zip(
+        ...collections: Array<Collection<unknown, unknown>>
+      ): Collection.Indexed<unknown>;
+
+      /**
+       * Returns a Collection "zipped" with the provided collections.
+       *
+       * Unlike `zip`, `zipAll` continues zipping until the longest collection is
+       * exhausted. Missing values from shorter collections are filled with `undefined`.
+       *
+       * ```js
+       * const a = List([ 1, 2 ]);
+       * const b = List([ 3, 4, 5 ]);
+       * const c = a.zipAll(b); // List [ [ 1, 3 ], [ 2, 4 ], [ undefined, 5 ] ]
+       * ```
+       */
+      zipAll<U>(other: Collection<unknown, U>): Collection.Indexed<[T, U]>;
+      zipAll<U, V>(
+        other: Collection<unknown, U>,
+        other2: Collection<unknown, V>
+      ): Collection.Indexed<[T, U, V]>;
+      zipAll(
+        ...collections: Array<Collection<unknown, unknown>>
+      ): Collection.Indexed<unknown>;
+
+      /**
+       * Returns a Collection of the same type "zipped" with the provided
+       * collections by using a custom `zipper` function.
+       *
+       * <!-- runkit:activate
+       *      { "preamble": "const { List } = require('immutable')" }
+       * -->
+       * ```js
+       * const a = List([ 1, 2, 3 ]);
+       * const b = List([ 4, 5, 6 ]);
+       * const c = a.zipWith((a, b) => a + b, b);
+       * // List [ 5, 7, 9 ]
+       * ```
+       */
+      zipWith<U, Z>(
+        zipper: (value: T, otherValue: U) => Z,
+        otherCollection: Collection<unknown, U>
+      ): Collection.Indexed<Z>;
+      zipWith<U, V, Z>(
+        zipper: (value: T, otherValue: U, thirdValue: V) => Z,
+        otherCollection: Collection<unknown, U>,
+        thirdCollection: Collection<unknown, V>
+      ): Collection.Indexed<Z>;
+      zipWith<Z>(
+        zipper: (...values: Array<unknown>) => Z,
+        ...collections: Array<Collection<unknown, unknown>>
+      ): Collection.Indexed<Z>;
+
+      // Search for value
+
+      /**
+       * Returns the first index at which a given value can be found in the
+       * Collection, or -1 if it is not present.
+       */
+      indexOf(searchValue: T): number;
+
+      /**
+       * Returns the last index at which a given value can be found in the
+       * Collection, or -1 if it is not present.
+       */
+      lastIndexOf(searchValue: T): number;
+
+      /**
+       * Returns the first index in the Collection where a value satisfies the
+       * provided predicate function. Otherwise -1 is returned.
+       */
+      findIndex(
+        predicate: (value: T, index: number, iter: this) => boolean,
+        context?: unknown
+      ): number;
+
+      /**
+       * Returns the last index in the Collection where a value satisfies the
+       * provided predicate function. Otherwise -1 is returned.
+       */
+      findLastIndex(
+        predicate: (value: T, index: number, iter: this) => boolean,
+        context?: unknown
+      ): number;
+
+      // Sequence algorithms
+
+      /**
+       * Returns a new Collection with other collections concatenated to this one.
+       */
+      concat<C>(
+        ...valuesOrCollections: Array<Iterable<C> | C>
+      ): Collection.Indexed<T | C>;
+
+      /**
+       * Returns a new Collection.Indexed with values passed through a
+       * `mapper` function.
+       *
+       * ```js
+       * const { Collection } = require('immutable')
+       * Collection.Indexed([1,2]).map(x => 10 * x)
+       * // Seq [ 1, 2 ]
+       * ```
+       *
+       * Note: `map()` always returns a new instance, even if it produced the
+       * same value at every step.
+       */
+      map<M>(
+        mapper: (value: T, key: number, iter: this) => M,
+        context?: unknown
+      ): Collection.Indexed<M>;
+
+      /**
+       * Flat-maps the Collection, returning a Collection of the same type.
+       *
+       * Similar to `collection.map(...).flatten(true)`.
+       */
+      flatMap<M>(
+        mapper: (value: T, key: number, iter: this) => Iterable<M>,
+        context?: unknown
+      ): Collection.Indexed<M>;
+
+      /**
+       * Returns a new Collection with only the values for which the `predicate`
+       * function returns true.
+       *
+       * Note: `filter()` always returns a new instance, even if it results in
+       * not filtering out any values.
+       */
+      filter<F extends T>(
+        predicate: (value: T, index: number, iter: this) => value is F,
+        context?: unknown
+      ): Collection.Indexed<F>;
+      filter(
+        predicate: (value: T, index: number, iter: this) => unknown,
+        context?: unknown
+      ): this;
+
+      /**
+       * Returns a new indexed Collection with the values for which the
+       * `predicate` function returns false and another for which is returns
+       * true.
+       */
+      partition<F extends T, C>(
+        predicate: (this: C, value: T, index: number, iter: this) => value is F,
+        context?: C
+      ): [Collection.Indexed<T>, Collection.Indexed<F>];
+      partition<C>(
+        predicate: (this: C, value: T, index: number, iter: this) => unknown,
+        context?: C
+      ): [this, this];
+
+      [Symbol.iterator](): IterableIterator<T>;
+    }
+
+    /**
+     * Set Collections only represent values. They have no associated keys or
+     * indices. Duplicate values are possible in the lazy `Seq.Set`s, however
+     * the concrete `Set` Collection does not allow duplicate values.
+     *
+     * Collection methods on Collection.Set such as `map` and `forEach` will provide
+     * the value as both the first and second arguments to the provided function.
+     *
+     * ```js
+     * const { Collection } = require('immutable')
+     * const seq = Collection.Set([ 'A', 'B', 'C' ])
+     * // Seq { "A", "B", "C" }
+     * seq.forEach((v, k) =>
+     *  assert.equal(v, k)
+     * )
+     * ```
+     */
+    namespace Set {}
+
+    /**
+     * Similar to `Collection()`, but always returns a Collection.Set.
+     *
+     * Note: `Collection.Set` is a factory function and not a class, and does
+     * not use the `new` keyword during construction.
+     */
+    function Set<T>(collection?: Iterable<T> | ArrayLike<T>): Collection.Set<T>;
+
+    interface Set<T> extends Collection<T, T> {
+      /**
+       * Deeply converts this Set collection to equivalent native JavaScript Array.
+       */
+      toJS(): Array<DeepCopy<T>>;
+
+      /**
+       * Shallowly converts this Set collection to equivalent native JavaScript Array.
+       */
+      toJSON(): Array<T>;
+
+      /**
+       * Shallowly converts this collection to an Array.
+       */
+      toArray(): Array<T>;
+
+      /**
+       * Returns Seq.Set.
+       * @override
+       */
+      toSeq(): Seq.Set<T>;
+
+      // Sequence algorithms
+
+      /**
+       * Returns a new Collection with other collections concatenated to this one.
+       */
+      concat<U>(...collections: Array<Iterable<U>>): Collection.Set<T | U>;
+
+      /**
+       * Returns a new Collection.Set with values passed through a
+       * `mapper` function.
+       *
+       * ```
+       * Collection.Set([ 1, 2 ]).map(x => 10 * x)
+       * // Seq { 1, 2 }
+       * ```
+       *
+       * Note: `map()` always returns a new instance, even if it produced the
+       * same value at every step.
+       */
+      map<M>(
+        mapper: (value: T, key: T, iter: this) => M,
+        context?: unknown
+      ): Collection.Set<M>;
+
+      /**
+       * Flat-maps the Collection, returning a Collection of the same type.
+       *
+       * Similar to `collection.map(...).flatten(true)`.
+       */
+      flatMap<M>(
+        mapper: (value: T, key: T, iter: this) => Iterable<M>,
+        context?: unknown
+      ): Collection.Set<M>;
+
+      /**
+       * Returns a new Collection with only the values for which the `predicate`
+       * function returns true.
+       *
+       * Note: `filter()` always returns a new instance, even if it results in
+       * not filtering out any values.
+       */
+      filter<F extends T>(
+        predicate: (value: T, key: T, iter: this) => value is F,
+        context?: unknown
+      ): Collection.Set<F>;
+      filter(
+        predicate: (value: T, key: T, iter: this) => unknown,
+        context?: unknown
+      ): this;
+
+      /**
+       * Returns a new set Collection with the values for which the
+       * `predicate` function returns false and another for which is returns
+       * true.
+       */
+      partition<F extends T, C>(
+        predicate: (this: C, value: T, key: T, iter: this) => value is F,
+        context?: C
+      ): [Collection.Set<T>, Collection.Set<F>];
+      partition<C>(
+        predicate: (this: C, value: T, key: T, iter: this) => unknown,
+        context?: C
+      ): [this, this];
+
+      [Symbol.iterator](): IterableIterator<T>;
+    }
+  }
+
+  /**
+   * Creates a Collection.
+   *
+   * The type of Collection created is based on the input.
+   *
+   *   * If an `Collection`, that same `Collection`.
+   *   * If an Array-like, an `Collection.Indexed`.
+   *   * If an Object with an Iterator defined, an `Collection.Indexed`.
+   *   * If an Object, an `Collection.Keyed`.
+   *
+   * This methods forces the conversion of Objects and Strings to Collections.
+   * If you want to ensure that a Collection of one item is returned, use
+   * `Seq.of`.
+   *
+   * Note: An Iterator itself will be treated as an object, becoming a `Seq.Keyed`,
+   * which is usually not what you want. You should turn your Iterator Object into
+   * an iterable object by defining a Symbol.iterator (or @@iterator) method which
+   * returns `this`.
+   *
+   * Note: `Collection` is a conversion function and not a class, and does not
+   * use the `new` keyword during construction.
+   */
+  function Collection<I extends Collection<unknown, unknown>>(collection: I): I;
+  function Collection<T>(
+    collection: Iterable<T> | ArrayLike<T>
+  ): Collection.Indexed<T>;
+  function Collection<V>(obj: {
+    [key: string]: V;
+  }): Collection.Keyed<string, V>;
+  function Collection<K = unknown, V = unknown>(): Collection<K, V>;
+
+  interface Collection<K, V> extends ValueObject {
+    // Value equality
+
+    /**
+     * True if this and the other Collection have value equality, as defined
+     * by `Immutable.is()`.
+     *
+     * Note: This is equivalent to `Immutable.is(this, other)`, but provided to
+     * allow for chained expressions.
+     */
+    equals(other: unknown): boolean;
+
+    /**
+     * Computes and returns the hashed identity for this Collection.
+     *
+     * The `hashCode` of a Collection is used to determine potential equality,
+     * and is used when adding this to a `Set` or as a key in a `Map`, enabling
+     * lookup via a different instance.
+     *
+     * <!-- runkit:activate
+     *      { "preamble": "const { Set,  List } = require('immutable')" }
+     * -->
+     * ```js
+     * const a = List([ 1, 2, 3 ]);
+     * const b = List([ 1, 2, 3 ]);
+     * assert.notStrictEqual(a, b); // different instances
+     * const set = Set([ a ]);
+     * assert.equal(set.has(b), true);
+     * ```
+     *
+     * If two values have the same `hashCode`, they are [not guaranteed
+     * to be equal][Hash Collision]. If two values have different `hashCode`s,
+     * they must not be equal.
+     *
+     * [Hash Collision]: https://en.wikipedia.org/wiki/Collision_(computer_science)
+     */
+    hashCode(): number;
+
+    // Reading values
+
+    /**
+     * Returns the value associated with the provided key, or notSetValue if
+     * the Collection does not contain this key.
+     *
+     * Note: it is possible a key may be associated with an `undefined` value,
+     * so if `notSetValue` is not provided and this method returns `undefined`,
+     * that does not guarantee the key was not found.
+     */
+    get<NSV>(key: K, notSetValue: NSV): V | NSV;
+    get(key: K): V | undefined;
+
+    /**
+     * True if a key exists within this `Collection`, using `Immutable.is`
+     * to determine equality
+     */
+    has(key: K): boolean;
+
+    /**
+     * True if a value exists within this `Collection`, using `Immutable.is`
+     * to determine equality
+     * @alias contains
+     */
+    includes(value: V): boolean;
+    contains(value: V): boolean;
+
+    /**
+     * In case the `Collection` is not empty returns the first element of the
+     * `Collection`.
+     * In case the `Collection` is empty returns the optional default
+     * value if provided, if no default value is provided returns undefined.
+     */
+    first<NSV>(notSetValue: NSV): V | NSV;
+    first(): V | undefined;
+
+    /**
+     * In case the `Collection` is not empty returns the last element of the
+     * `Collection`.
+     * In case the `Collection` is empty returns the optional default
+     * value if provided, if no default value is provided returns undefined.
+     */
+    last<NSV>(notSetValue: NSV): V | NSV;
+    last(): V | undefined;
+
+    // Reading deep values
+
+    /**
+     * Returns the value found by following a path of keys or indices through
+     * nested Collections.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map, List } = require('immutable')
+     * const deepData = Map({ x: List([ Map({ y: 123 }) ]) });
+     * deepData.getIn(['x', 0, 'y']) // 123
+     * ```
+     *
+     * Plain JavaScript Object or Arrays may be nested within an Immutable.js
+     * Collection, and getIn() can access those values as well:
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map, List } = require('immutable')
+     * const deepData = Map({ x: [ { y: 123 } ] });
+     * deepData.getIn(['x', 0, 'y']) // 123
+     * ```
+     */
+    getIn(searchKeyPath: Iterable<unknown>, notSetValue?: unknown): unknown;
+
+    /**
+     * True if the result of following a path of keys or indices through nested
+     * Collections results in a set value.
+     */
+    hasIn(searchKeyPath: Iterable<unknown>): boolean;
+
+    // Persistent changes
+
+    /**
+     * This can be very useful as a way to "chain" a normal function into a
+     * sequence of methods. RxJS calls this "let" and lodash calls it "thru".
+     *
+     * For example, to sum a Seq after mapping and filtering:
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Seq } = require('immutable')
+     *
+     * function sum(collection) {
+     *   return collection.reduce((sum, x) => sum + x, 0)
+     * }
+     *
+     * Seq([ 1, 2, 3 ])
+     *   .map(x => x + 1)
+     *   .filter(x => x % 2 === 0)
+     *   .update(sum)
+     * // 6
+     * ```
+     */
+    update<R>(updater: (value: this) => R): R;
+
+    // Conversion to JavaScript types
+
+    /**
+     * Deeply converts this Collection to equivalent native JavaScript Array or Object.
+     *
+     * `Collection.Indexed`, and `Collection.Set` become `Array`, while
+     * `Collection.Keyed` become `Object`, converting keys to Strings.
+     */
+    toJS():
+      | Array<DeepCopy<V>>
+      | { [key in string | number | symbol]: DeepCopy<V> };
+
+    /**
+     * Shallowly converts this Collection to equivalent native JavaScript Array or Object.
+     *
+     * `Collection.Indexed`, and `Collection.Set` become `Array`, while
+     * `Collection.Keyed` become `Object`, converting keys to Strings.
+     */
+    toJSON(): Array<V> | { [key in string | number | symbol]: V };
+
+    /**
+     * Shallowly converts this collection to an Array.
+     *
+     * `Collection.Indexed`, and `Collection.Set` produce an Array of values.
+     * `Collection.Keyed` produce an Array of [key, value] tuples.
+     */
+    toArray(): Array<V> | Array<[K, V]>;
+
+    /**
+     * Shallowly converts this Collection to an Object.
+     *
+     * Converts keys to Strings.
+     */
+    toObject(): { [key: string]: V };
+
+    // Conversion to Collections
+
+    /**
+     * Converts this Collection to a Map, Throws if keys are not hashable.
+     *
+     * Note: This is equivalent to `Map(this.toKeyedSeq())`, but provided
+     * for convenience and to allow for chained expressions.
+     */
+    toMap(): Map<K, V>;
+
+    /**
+     * Converts this Collection to a Map, maintaining the order of iteration.
+     *
+     * Note: This is equivalent to `OrderedMap(this.toKeyedSeq())`, but
+     * provided for convenience and to allow for chained expressions.
+     */
+    toOrderedMap(): OrderedMap<K, V>;
+
+    /**
+     * Converts this Collection to a Set, discarding keys. Throws if values
+     * are not hashable.
+     *
+     * Note: This is equivalent to `Set(this)`, but provided to allow for
+     * chained expressions.
+     */
+    toSet(): Set<V>;
+
+    /**
+     * Converts this Collection to a Set, maintaining the order of iteration and
+     * discarding keys.
+     *
+     * Note: This is equivalent to `OrderedSet(this.valueSeq())`, but provided
+     * for convenience and to allow for chained expressions.
+     */
+    toOrderedSet(): OrderedSet<V>;
+
+    /**
+     * Converts this Collection to a List, discarding keys.
+     *
+     * This is similar to `List(collection)`, but provided to allow for chained
+     * expressions. However, when called on `Map` or other keyed collections,
+     * `collection.toList()` discards the keys and creates a list of only the
+     * values, whereas `List(collection)` creates a list of entry tuples.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map, List } = require('immutable')
+     * var myMap = Map({ a: 'Apple', b: 'Banana' })
+     * List(myMap) // List [ [ "a", "Apple" ], [ "b", "Banana" ] ]
+     * myMap.toList() // List [ "Apple", "Banana" ]
+     * ```
+     */
+    toList(): List<V>;
+
+    /**
+     * Converts this Collection to a Stack, discarding keys. Throws if values
+     * are not hashable.
+     *
+     * Note: This is equivalent to `Stack(this)`, but provided to allow for
+     * chained expressions.
+     */
+    toStack(): Stack<V>;
+
+    // Conversion to Seq
+
+    /**
+     * Converts this Collection to a Seq of the same kind (indexed,
+     * keyed, or set).
+     */
+    toSeq(): Seq<K, V>;
+
+    /**
+     * Returns a Seq.Keyed from this Collection where indices are treated as keys.
+     *
+     * This is useful if you want to operate on an
+     * Collection.Indexed and preserve the [index, value] pairs.
+     *
+     * The returned Seq will have identical iteration order as
+     * this Collection.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Seq } = require('immutable')
+     * const indexedSeq = Seq([ 'A', 'B', 'C' ])
+     * // Seq [ "A", "B", "C" ]
+     * indexedSeq.filter(v => v === 'B')
+     * // Seq [ "B" ]
+     * const keyedSeq = indexedSeq.toKeyedSeq()
+     * // Seq { 0: "A", 1: "B", 2: "C" }
+     * keyedSeq.filter(v => v === 'B')
+     * // Seq { 1: "B" }
+     * ```
+     */
+    toKeyedSeq(): Seq.Keyed<K, V>;
+
+    /**
+     * Returns an Seq.Indexed of the values of this Collection, discarding keys.
+     */
+    toIndexedSeq(): Seq.Indexed<V>;
+
+    /**
+     * Returns a Seq.Set of the values of this Collection, discarding keys.
+     */
+    toSetSeq(): Seq.Set<V>;
+
+    // Iterators
+
+    /**
+     * An iterator of this `Collection`'s keys.
+     *
+     * Note: this will return an ES6 iterator which does not support
+     * Immutable.js sequence algorithms. Use `keySeq` instead, if this is
+     * what you want.
+     */
+    keys(): IterableIterator<K>;
+
+    /**
+     * An iterator of this `Collection`'s values.
+     *
+     * Note: this will return an ES6 iterator which does not support
+     * Immutable.js sequence algorithms. Use `valueSeq` instead, if this is
+     * what you want.
+     */
+    values(): IterableIterator<V>;
+
+    /**
+     * An iterator of this `Collection`'s entries as `[ key, value ]` tuples.
+     *
+     * Note: this will return an ES6 iterator which does not support
+     * Immutable.js sequence algorithms. Use `entrySeq` instead, if this is
+     * what you want.
+     */
+    entries(): IterableIterator<[K, V]>;
+
+    [Symbol.iterator](): IterableIterator<unknown>;
+
+    // Collections (Seq)
+
+    /**
+     * Returns a new Seq.Indexed of the keys of this Collection,
+     * discarding values.
+     */
+    keySeq(): Seq.Indexed<K>;
+
+    /**
+     * Returns an Seq.Indexed of the values of this Collection, discarding keys.
+     */
+    valueSeq(): Seq.Indexed<V>;
+
+    /**
+     * Returns a new Seq.Indexed of [key, value] tuples.
+     */
+    entrySeq(): Seq.Indexed<[K, V]>;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new Collection of the same type with values passed through a
+     * `mapper` function.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Collection } = require('immutable')
+     * Collection({ a: 1, b: 2 }).map(x => 10 * x)
+     * // Seq { "a": 10, "b": 20 }
+     * ```
+     *
+     * Note: `map()` always returns a new instance, even if it produced the same
+     * value at every step.
+     */
+    map<M>(
+      mapper: (value: V, key: K, iter: this) => M,
+      context?: unknown
+    ): Collection<K, M>;
+
+    /**
+     * Note: used only for sets, which return Collection<M, M> but are otherwise
+     * identical to normal `map()`.
+     *
+     * @ignore
+     */
+    map(...args: Array<never>): unknown;
+
+    /**
+     * Returns a new Collection of the same type with only the entries for which
+     * the `predicate` function returns true.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * Map({ a: 1, b: 2, c: 3, d: 4}).filter(x => x % 2 === 0)
+     * // Map { "b": 2, "d": 4 }
+     * ```
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends V>(
+      predicate: (value: V, key: K, iter: this) => value is F,
+      context?: unknown
+    ): Collection<K, F>;
+    filter(
+      predicate: (value: V, key: K, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Collection of the same type with only the entries for which
+     * the `predicate` function returns false.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * Map({ a: 1, b: 2, c: 3, d: 4}).filterNot(x => x % 2 === 0)
+     * // Map { "a": 1, "c": 3 }
+     * ```
+     *
+     * Note: `filterNot()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filterNot(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Collection with the values for which the `predicate`
+     * function returns false and another for which is returns true.
+     */
+    partition<F extends V, C>(
+      predicate: (this: C, value: V, key: K, iter: this) => value is F,
+      context?: C
+    ): [Collection<K, V>, Collection<K, F>];
+    partition<C>(
+      predicate: (this: C, value: V, key: K, iter: this) => unknown,
+      context?: C
+    ): [this, this];
+
+    /**
+     * Returns a new Collection of the same type in reverse order.
+     */
+    reverse(): this;
+
+    /**
+     * Returns a new Collection of the same type which includes the same entries,
+     * stably sorted by using a `comparator`.
+     *
+     * If a `comparator` is not provided, a default comparator uses `<` and `>`.
+     *
+     * `comparator(valueA, valueB)`:
+     *
+     *   * Returns `0` if the elements should not be swapped.
+     *   * Returns `-1` (or any negative number) if `valueA` comes before `valueB`
+     *   * Returns `1` (or any positive number) if `valueA` comes after `valueB`
+     *   * Alternatively, can return a value of the `PairSorting` enum type
+     *   * Is pure, i.e. it must always return the same value for the same pair
+     *     of values.
+     *
+     * When sorting collections which have no defined order, their ordered
+     * equivalents will be returned. e.g. `map.sort()` returns OrderedMap.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * Map({ "c": 3, "a": 1, "b": 2 }).sort((a, b) => {
+     *   if (a < b) { return -1; }
+     *   if (a > b) { return 1; }
+     *   if (a === b) { return 0; }
+     * });
+     * // OrderedMap { "a": 1, "b": 2, "c": 3 }
+     * ```
+     *
+     * Note: `sort()` Always returns a new instance, even if the original was
+     * already sorted.
+     *
+     * Note: This is always an eager operation.
+     */
+    sort(comparator?: Comparator<V>): this;
+
+    /**
+     * Like `sort`, but also accepts a `comparatorValueMapper` which allows for
+     * sorting by more sophisticated means:
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { Map } = require('immutable')
+     * const beattles = Map({
+     *   John: { name: "Lennon" },
+     *   Paul: { name: "McCartney" },
+     *   George: { name: "Harrison" },
+     *   Ringo: { name: "Starr" },
+     * });
+     * beattles.sortBy(member => member.name);
+     * ```
+     *
+     * Note: `sortBy()` Always returns a new instance, even if the original was
+     * already sorted.
+     *
+     * Note: This is always an eager operation.
+     */
+    sortBy<C>(
+      comparatorValueMapper: (value: V, key: K, iter: this) => C,
+      comparator?: Comparator<C>
+    ): this;
+
+    /**
+     * Returns a `Map` of `Collection`, grouped by the return
+     * value of the `grouper` function.
+     *
+     * Note: This is always an eager operation.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List, Map } = require('immutable')
+     * const listOfMaps = List([
+     *   Map({ v: 0 }),
+     *   Map({ v: 1 }),
+     *   Map({ v: 1 }),
+     *   Map({ v: 0 }),
+     *   Map({ v: 2 })
+     * ])
+     * const groupsOfMaps = listOfMaps.groupBy(x => x.get('v'))
+     * // Map {
+     * //   0: List [ Map{ "v": 0 }, Map { "v": 0 } ],
+     * //   1: List [ Map{ "v": 1 }, Map { "v": 1 } ],
+     * //   2: List [ Map{ "v": 2 } ],
+     * // }
+     * ```
+     */
+    groupBy<G>(
+      grouper: (value: V, key: K, iter: this) => G,
+      context?: unknown
+    ): Map<G, this>;
+
+    // Side effects
+
+    /**
+     * The `sideEffect` is executed for every entry in the Collection.
+     *
+     * Unlike `Array#forEach`, if any call of `sideEffect` returns
+     * `false`, the iteration will stop. Returns the number of entries iterated
+     * (including the last iteration which returned false).
+     */
+    forEach(
+      sideEffect: (value: V, key: K, iter: this) => unknown,
+      context?: unknown
+    ): number;
+
+    // Creating subsets
+
+    /**
+     * Returns a new Collection of the same type representing a portion of this
+     * Collection from start up to but not including end.
+     *
+     * If begin is negative, it is offset from the end of the Collection. e.g.
+     * `slice(-2)` returns a Collection of the last two entries. If it is not
+     * provided the new Collection will begin at the beginning of this Collection.
+     *
+     * If end is negative, it is offset from the end of the Collection. e.g.
+     * `slice(0, -1)` returns a Collection of everything but the last entry. If
+     * it is not provided, the new Collection will continue through the end of
+     * this Collection.
+     *
+     * If the requested slice is equivalent to the current Collection, then it
+     * will return itself.
+     */
+    slice(begin?: number, end?: number): this;
+
+    /**
+     * Returns a new Collection of the same type containing all entries except
+     * the first.
+     */
+    rest(): this;
+
+    /**
+     * Returns a new Collection of the same type containing all entries except
+     * the last.
+     */
+    butLast(): this;
+
+    /**
+     * Returns a new Collection of the same type which excludes the first `amount`
+     * entries from this Collection.
+     */
+    skip(amount: number): this;
+
+    /**
+     * Returns a new Collection of the same type which excludes the last `amount`
+     * entries from this Collection.
+     */
+    skipLast(amount: number): this;
+
+    /**
+     * Returns a new Collection of the same type which includes entries starting
+     * from when `predicate` first returns false.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List } = require('immutable')
+     * List([ 'dog', 'frog', 'cat', 'hat', 'god' ])
+     *   .skipWhile(x => x.match(/g/))
+     * // List [ "cat", "hat", "god" ]
+     * ```
+     */
+    skipWhile(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Collection of the same type which includes entries starting
+     * from when `predicate` first returns true.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List } = require('immutable')
+     * List([ 'dog', 'frog', 'cat', 'hat', 'god' ])
+     *   .skipUntil(x => x.match(/hat/))
+     * // List [ "hat", "god" ]
+     * ```
+     */
+    skipUntil(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Collection of the same type which includes the first `amount`
+     * entries from this Collection.
+     */
+    take(amount: number): this;
+
+    /**
+     * Returns a new Collection of the same type which includes the last `amount`
+     * entries from this Collection.
+     */
+    takeLast(amount: number): this;
+
+    /**
+     * Returns a new Collection of the same type which includes entries from this
+     * Collection as long as the `predicate` returns true.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List } = require('immutable')
+     * List([ 'dog', 'frog', 'cat', 'hat', 'god' ])
+     *   .takeWhile(x => x.match(/o/))
+     * // List [ "dog", "frog" ]
+     * ```
+     */
+    takeWhile(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Collection of the same type which includes entries from this
+     * Collection as long as the `predicate` returns false.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List } = require('immutable')
+     * List([ 'dog', 'frog', 'cat', 'hat', 'god' ])
+     *   .takeUntil(x => x.match(/at/))
+     * // List [ "dog", "frog" ]
+     * ```
+     */
+    takeUntil(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): this;
+
+    // Combination
+
+    /**
+     * Returns a new Collection of the same type with other values and
+     * collection-like concatenated to this one.
+     *
+     * For Seqs, all entries will be present in the resulting Seq, even if they
+     * have the same key.
+     */
+    concat(
+      ...valuesOrCollections: Array<unknown>
+    ): Collection<unknown, unknown>;
+
+    /**
+     * Flattens nested Collections.
+     *
+     * Will deeply flatten the Collection by default, returning a Collection of the
+     * same type, but a `depth` can be provided in the form of a number or
+     * boolean (where true means to shallowly flatten one level). A depth of 0
+     * (or shallow: false) will deeply flatten.
+     *
+     * Flattens only others Collection, not Arrays or Objects.
+     *
+     * Note: `flatten(true)` operates on Collection<unknown, Collection<K, V>> and
+     * returns Collection<K, V>
+     */
+    flatten(depth?: number): Collection<unknown, unknown>;
+    flatten(shallow?: boolean): Collection<unknown, unknown>;
+
+    /**
+     * Flat-maps the Collection, returning a Collection of the same type.
+     *
+     * Similar to `collection.map(...).flatten(true)`.
+     */
+    flatMap<M>(
+      mapper: (value: V, key: K, iter: this) => Iterable<M>,
+      context?: unknown
+    ): Collection<K, M>;
+
+    /**
+     * Flat-maps the Collection, returning a Collection of the same type.
+     *
+     * Similar to `collection.map(...).flatten(true)`.
+     * Used for Dictionaries only.
+     */
+    flatMap<KM, VM>(
+      mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+      context?: unknown
+    ): Collection<KM, VM>;
+
+    // Reducing a value
+
+    /**
+     * Reduces the Collection to a value by calling the `reducer` for every entry
+     * in the Collection and passing along the reduced value.
+     *
+     * If `initialReduction` is not provided, the first item in the
+     * Collection will be used.
+     *
+     * @see `Array#reduce`.
+     */
+    reduce<R>(
+      reducer: (reduction: R, value: V, key: K, iter: this) => R,
+      initialReduction: R,
+      context?: unknown
+    ): R;
+    reduce<R>(
+      reducer: (reduction: V | R, value: V, key: K, iter: this) => R
+    ): R;
+
+    /**
+     * Reduces the Collection in reverse (from the right side).
+     *
+     * Note: Similar to this.reverse().reduce(), and provided for parity
+     * with `Array#reduceRight`.
+     */
+    reduceRight<R>(
+      reducer: (reduction: R, value: V, key: K, iter: this) => R,
+      initialReduction: R,
+      context?: unknown
+    ): R;
+    reduceRight<R>(
+      reducer: (reduction: V | R, value: V, key: K, iter: this) => R
+    ): R;
+
+    /**
+     * True if `predicate` returns true for all entries in the Collection.
+     */
+    every(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): boolean;
+
+    /**
+     * True if `predicate` returns true for any entry in the Collection.
+     */
+    some(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): boolean;
+
+    /**
+     * Joins values together as a string, inserting a separator between each.
+     * The default separator is `","`.
+     */
+    join(separator?: string): string;
+
+    /**
+     * Returns true if this Collection includes no values.
+     *
+     * For some lazy `Seq`, `isEmpty` might need to iterate to determine
+     * emptiness. At most one iteration will occur.
+     */
+    isEmpty(): boolean;
+
+    /**
+     * Returns the size of this Collection.
+     *
+     * Regardless of if this Collection can describe its size lazily (some Seqs
+     * cannot), this method will always return the correct size. E.g. it
+     * evaluates a lazy `Seq` if necessary.
+     *
+     * If `predicate` is provided, then this returns the count of entries in the
+     * Collection for which the `predicate` returns true.
+     */
+    count(): number;
+    count(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): number;
+
+    /**
+     * Returns a `Seq.Keyed` of counts, grouped by the return value of
+     * the `grouper` function.
+     *
+     * Note: This is not a lazy operation.
+     */
+    countBy<G>(
+      grouper: (value: V, key: K, iter: this) => G,
+      context?: unknown
+    ): Map<G, number>;
+
+    // Search for value
+
+    /**
+     * Returns the first value for which the `predicate` returns true.
+     */
+    find(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown,
+      notSetValue?: V
+    ): V | undefined;
+
+    /**
+     * Returns the last value for which the `predicate` returns true.
+     *
+     * Note: `predicate` will be called for each entry in reverse.
+     */
+    findLast(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown,
+      notSetValue?: V
+    ): V | undefined;
+
+    /**
+     * Returns the first [key, value] entry for which the `predicate` returns true.
+     */
+    findEntry(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown,
+      notSetValue?: V
+    ): [K, V] | undefined;
+
+    /**
+     * Returns the last [key, value] entry for which the `predicate`
+     * returns true.
+     *
+     * Note: `predicate` will be called for each entry in reverse.
+     */
+    findLastEntry(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown,
+      notSetValue?: V
+    ): [K, V] | undefined;
+
+    /**
+     * Returns the key for which the `predicate` returns true.
+     */
+    findKey(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): K | undefined;
+
+    /**
+     * Returns the last key for which the `predicate` returns true.
+     *
+     * Note: `predicate` will be called for each entry in reverse.
+     */
+    findLastKey(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): K | undefined;
+
+    /**
+     * Returns the key associated with the search value, or undefined.
+     */
+    keyOf(searchValue: V): K | undefined;
+
+    /**
+     * Returns the last key associated with the search value, or undefined.
+     */
+    lastKeyOf(searchValue: V): K | undefined;
+
+    /**
+     * Returns the maximum value in this collection. If any values are
+     * comparatively equivalent, the first one found will be returned.
+     *
+     * The `comparator` is used in the same way as `Collection#sort`. If it is not
+     * provided, the default comparator is `>`.
+     *
+     * When two values are considered equivalent, the first encountered will be
+     * returned. Otherwise, `max` will operate independent of the order of input
+     * as long as the comparator is commutative. The default comparator `>` is
+     * commutative *only* when types do not differ.
+     *
+     * If `comparator` returns 0 and either value is NaN, undefined, or null,
+     * that value will be returned.
+     */
+    max(comparator?: Comparator<V>): V | undefined;
+
+    /**
+     * Like `max`, but also accepts a `comparatorValueMapper` which allows for
+     * comparing by more sophisticated means:
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List, } = require('immutable');
+     * const l = List([
+     *   { name: 'Bob', avgHit: 1 },
+     *   { name: 'Max', avgHit: 3 },
+     *   { name: 'Lili', avgHit: 2 } ,
+     * ]);
+     * l.maxBy(i => i.avgHit); // will output { name: 'Max', avgHit: 3 }
+     * ```
+     */
+    maxBy<C>(
+      comparatorValueMapper: (value: V, key: K, iter: this) => C,
+      comparator?: Comparator<C>
+    ): V | undefined;
+
+    /**
+     * Returns the minimum value in this collection. If any values are
+     * comparatively equivalent, the first one found will be returned.
+     *
+     * The `comparator` is used in the same way as `Collection#sort`. If it is not
+     * provided, the default comparator is `<`.
+     *
+     * When two values are considered equivalent, the first encountered will be
+     * returned. Otherwise, `min` will operate independent of the order of input
+     * as long as the comparator is commutative. The default comparator `<` is
+     * commutative *only* when types do not differ.
+     *
+     * If `comparator` returns 0 and either value is NaN, undefined, or null,
+     * that value will be returned.
+     */
+    min(comparator?: Comparator<V>): V | undefined;
+
+    /**
+     * Like `min`, but also accepts a `comparatorValueMapper` which allows for
+     * comparing by more sophisticated means:
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List, } = require('immutable');
+     * const l = List([
+     *   { name: 'Bob', avgHit: 1 },
+     *   { name: 'Max', avgHit: 3 },
+     *   { name: 'Lili', avgHit: 2 } ,
+     * ]);
+     * l.minBy(i => i.avgHit); // will output { name: 'Bob', avgHit: 1 }
+     * ```
+     */
+    minBy<C>(
+      comparatorValueMapper: (value: V, key: K, iter: this) => C,
+      comparator?: Comparator<C>
+    ): V | undefined;
+
+    // Comparison
+
+    /**
+     * True if `iter` includes every value in this Collection.
+     */
+    isSubset(iter: Iterable<V>): boolean;
+
+    /**
+     * True if this Collection includes every value in `iter`.
+     */
+    isSuperset(iter: Iterable<V>): boolean;
+  }
+
+  /**
+   * The interface to fulfill to qualify as a Value Object.
+   */
+  interface ValueObject {
+    /**
+     * True if this and the other Collection have value equality, as defined
+     * by `Immutable.is()`.
+     *
+     * Note: This is equivalent to `Immutable.is(this, other)`, but provided to
+     * allow for chained expressions.
+     */
+    equals(other: unknown): boolean;
+
+    /**
+     * Computes and returns the hashed identity for this Collection.
+     *
+     * The `hashCode` of a Collection is used to determine potential equality,
+     * and is used when adding this to a `Set` or as a key in a `Map`, enabling
+     * lookup via a different instance.
+     *
+     * <!-- runkit:activate -->
+     * ```js
+     * const { List, Set } = require('immutable');
+     * const a = List([ 1, 2, 3 ]);
+     * const b = List([ 1, 2, 3 ]);
+     * assert.notStrictEqual(a, b); // different instances
+     * const set = Set([ a ]);
+     * assert.equal(set.has(b), true);
+     * ```
+     *
+     * Note: hashCode() MUST return a Uint32 number. The easiest way to
+     * guarantee this is to return `myHash | 0` from a custom implementation.
+     *
+     * If two values have the same `hashCode`, they are [not guaranteed
+     * to be equal][Hash Collision]. If two values have different `hashCode`s,
+     * they must not be equal.
+     *
+     * Note: `hashCode()` is not guaranteed to always be called before
+     * `equals()`. Most but not all Immutable.js collections use hash codes to
+     * organize their internal data structures, while all Immutable.js
+     * collections use equality during lookups.
+     *
+     * [Hash Collision]: https://en.wikipedia.org/wiki/Collision_(computer_science)
+     */
+    hashCode(): number;
+  }
+
+  /**
+   * Deeply converts plain JS objects and arrays to Immutable Maps and Lists.
+   *
+   * `fromJS` will convert Arrays and [array-like objects][2] to a List, and
+   * plain objects (without a custom prototype) to a Map. [Iterable objects][3]
+   * may be converted to List, Map, or Set.
+   *
+   * If a `reviver` is optionally provided, it will be called with every
+   * collection as a Seq (beginning with the most nested collections
+   * and proceeding to the top-level collection itself), along with the key
+   * referring to each collection and the parent JS object provided as `this`.
+   * For the top level, object, the key will be `""`. This `reviver` is expected
+   * to return a new Immutable Collection, allowing for custom conversions from
+   * deep JS objects. Finally, a `path` is provided which is the sequence of
+   * keys to this value from the starting value.
+   *
+   * `reviver` acts similarly to the [same parameter in `JSON.parse`][1].
+   *
+   * If `reviver` is not provided, the default behavior will convert Objects
+   * into Maps and Arrays into Lists like so:
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { fromJS, isKeyed } = require('immutable')
+   * function (key, value) {
+   *   return isKeyed(value) ? value.toMap() : value.toList()
+   * }
+   * ```
+   *
+   * Accordingly, this example converts native JS data to OrderedMap and List:
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { fromJS, isKeyed } = require('immutable')
+   * fromJS({ a: {b: [10, 20, 30]}, c: 40}, function (key, value, path) {
+   *   console.log(key, value, path)
+   *   return isKeyed(value) ? value.toOrderedMap() : value.toList()
+   * })
+   *
+   * > "b", [ 10, 20, 30 ], [ "a", "b" ]
+   * > "a", {b: [10, 20, 30]}, [ "a" ]
+   * > "", {a: {b: [10, 20, 30]}, c: 40}, []
+   * ```
+   *
+   * Keep in mind, when using JS objects to construct Immutable Maps, that
+   * JavaScript Object properties are always strings, even if written in a
+   * quote-less shorthand, while Immutable Maps accept keys of any type.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { Map } = require('immutable')
+   * let obj = { 1: "one" };
+   * Object.keys(obj); // [ "1" ]
+   * assert.equal(obj["1"], obj[1]); // "one" === "one"
+   *
+   * let map = Map(obj);
+   * assert.notEqual(map.get("1"), map.get(1)); // "one" !== undefined
+   * ```
+   *
+   * Property access for JavaScript Objects first converts the key to a string,
+   * but since Immutable Map keys can be of any type the argument to `get()` is
+   * not altered.
+   *
+   * [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Example.3A_Using_the_reviver_parameter
+   *      "Using the reviver parameter"
+   * [2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#working_with_array-like_objects
+   *      "Working with array-like objects"
+   * [3]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol
+   *      "The iterable protocol"
+   */
+  function fromJS<JSValue>(
+    jsValue: JSValue,
+    reviver?: undefined
+  ): FromJS<JSValue>;
+  function fromJS(
+    jsValue: unknown,
+    reviver?: (
+      key: string | number,
+      sequence: Collection.Keyed<string, unknown> | Collection.Indexed<unknown>,
+      path?: Array<string | number>
+    ) => unknown
+  ): Collection<unknown, unknown>;
+
+  type FromJS<JSValue> = JSValue extends FromJSNoTransform
+    ? JSValue
+    : JSValue extends Array<any>
+    ? FromJSArray<JSValue>
+    : JSValue extends {}
+    ? FromJSObject<JSValue>
+    : any;
+
+  type FromJSNoTransform =
+    | Collection<any, any>
+    | number
+    | string
+    | null
+    | undefined;
+
+  type FromJSArray<JSValue> = JSValue extends Array<infer T>
+    ? List<FromJS<T>>
+    : never;
+
+  type FromJSObject<JSValue> = JSValue extends {}
+    ? Map<keyof JSValue, FromJS<JSValue[keyof JSValue]>>
+    : never;
+
+  /**
+   * Value equality check with semantics similar to `Object.is`, but treats
+   * Immutable `Collection`s as values, equal if the second `Collection` includes
+   * equivalent values.
+   *
+   * It's used throughout Immutable when checking for equality, including `Map`
+   * key equality and `Set` membership.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { Map, is } = require('immutable')
+   * const map1 = Map({ a: 1, b: 1, c: 1 })
+   * const map2 = Map({ a: 1, b: 1, c: 1 })
+   * assert.equal(map1 !== map2, true)
+   * assert.equal(Object.is(map1, map2), false)
+   * assert.equal(is(map1, map2), true)
+   * ```
+   *
+   * `is()` compares primitive types like strings and numbers, Immutable.js
+   * collections like `Map` and `List`, but also any custom object which
+   * implements `ValueObject` by providing `equals()` and `hashCode()` methods.
+   *
+   * Note: Unlike `Object.is`, `Immutable.is` assumes `0` and `-0` are the same
+   * value, matching the behavior of ES6 Map key equality.
+   */
+  function is(first: unknown, second: unknown): boolean;
+
+  /**
+   * The `hash()` function is an important part of how Immutable determines if
+   * two values are equivalent and is used to determine how to store those
+   * values. Provided with any value, `hash()` will return a 31-bit integer.
+   *
+   * When designing Objects which may be equal, it's important that when a
+   * `.equals()` method returns true, that both values `.hashCode()` method
+   * return the same value. `hash()` may be used to produce those values.
+   *
+   * For non-Immutable Objects that do not provide a `.hashCode()` functions
+   * (including plain Objects, plain Arrays, Date objects, etc), a unique hash
+   * value will be created for each *instance*. That is, the create hash
+   * represents referential equality, and not value equality for Objects. This
+   * ensures that if that Object is mutated over time that its hash code will
+   * remain consistent, allowing Objects to be used as keys and values in
+   * Immutable.js collections.
+   *
+   * Note that `hash()` attempts to balance between speed and avoiding
+   * collisions, however it makes no attempt to produce secure hashes.
+   *
+   * *New in Version 4.0*
+   */
+  function hash(value: unknown): number;
+
+  /**
+   * True if `maybeImmutable` is an Immutable Collection or Record.
+   *
+   * Note: Still returns true even if the collections is within a `withMutations()`.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { isImmutable, Map, List, Stack } = require('immutable');
+   * isImmutable([]); // false
+   * isImmutable({}); // false
+   * isImmutable(Map()); // true
+   * isImmutable(List()); // true
+   * isImmutable(Stack()); // true
+   * isImmutable(Map().asMutable()); // true
+   * ```
+   */
+  function isImmutable(
+    maybeImmutable: unknown
+  ): maybeImmutable is Collection<unknown, unknown>;
+
+  /**
+   * True if `maybeCollection` is a Collection, or any of its subclasses.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { isCollection, Map, List, Stack } = require('immutable');
+   * isCollection([]); // false
+   * isCollection({}); // false
+   * isCollection(Map()); // true
+   * isCollection(List()); // true
+   * isCollection(Stack()); // true
+   * ```
+   */
+  function isCollection(
+    maybeCollection: unknown
+  ): maybeCollection is Collection<unknown, unknown>;
+
+  /**
+   * True if `maybeKeyed` is a Collection.Keyed, or any of its subclasses.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { isKeyed, Map, List, Stack } = require('immutable');
+   * isKeyed([]); // false
+   * isKeyed({}); // false
+   * isKeyed(Map()); // true
+   * isKeyed(List()); // false
+   * isKeyed(Stack()); // false
+   * ```
+   */
+  function isKeyed(
+    maybeKeyed: unknown
+  ): maybeKeyed is Collection.Keyed<unknown, unknown>;
+
+  /**
+   * True if `maybeIndexed` is a Collection.Indexed, or any of its subclasses.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { isIndexed, Map, List, Stack, Set } = require('immutable');
+   * isIndexed([]); // false
+   * isIndexed({}); // false
+   * isIndexed(Map()); // false
+   * isIndexed(List()); // true
+   * isIndexed(Stack()); // true
+   * isIndexed(Set()); // false
+   * ```
+   */
+  function isIndexed(
+    maybeIndexed: unknown
+  ): maybeIndexed is Collection.Indexed<unknown>;
+
+  /**
+   * True if `maybeAssociative` is either a Keyed or Indexed Collection.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { isAssociative, Map, List, Stack, Set } = require('immutable');
+   * isAssociative([]); // false
+   * isAssociative({}); // false
+   * isAssociative(Map()); // true
+   * isAssociative(List()); // true
+   * isAssociative(Stack()); // true
+   * isAssociative(Set()); // false
+   * ```
+   */
+  function isAssociative(
+    maybeAssociative: unknown
+  ): maybeAssociative is
+    | Collection.Keyed<unknown, unknown>
+    | Collection.Indexed<unknown>;
+
+  /**
+   * True if `maybeOrdered` is a Collection where iteration order is well
+   * defined. True for Collection.Indexed as well as OrderedMap and OrderedSet.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { isOrdered, Map, OrderedMap, List, Set } = require('immutable');
+   * isOrdered([]); // false
+   * isOrdered({}); // false
+   * isOrdered(Map()); // false
+   * isOrdered(OrderedMap()); // true
+   * isOrdered(List()); // true
+   * isOrdered(Set()); // false
+   * ```
+   */
+  function isOrdered(maybeOrdered: unknown): boolean;
+
+  /**
+   * True if `maybeValue` is a JavaScript Object which has *both* `equals()`
+   * and `hashCode()` methods.
+   *
+   * Any two instances of *value objects* can be compared for value equality with
+   * `Immutable.is()` and can be used as keys in a `Map` or members in a `Set`.
+   */
+  function isValueObject(maybeValue: unknown): maybeValue is ValueObject;
+
+  /**
+   * True if `maybeSeq` is a Seq.
+   */
+  function isSeq(
+    maybeSeq: unknown
+  ): maybeSeq is
+    | Seq.Indexed<unknown>
+    | Seq.Keyed<unknown, unknown>
+    | Seq.Set<unknown>;
+
+  /**
+   * True if `maybeList` is a List.
+   */
+  function isList(maybeList: unknown): maybeList is List<unknown>;
+
+  /**
+   * True if `maybeMap` is a Map.
+   *
+   * Also true for OrderedMaps.
+   */
+  function isMap(maybeMap: unknown): maybeMap is Map<unknown, unknown>;
+
+  /**
+   * True if `maybeOrderedMap` is an OrderedMap.
+   */
+  function isOrderedMap(
+    maybeOrderedMap: unknown
+  ): maybeOrderedMap is OrderedMap<unknown, unknown>;
+
+  /**
+   * True if `maybeStack` is a Stack.
+   */
+  function isStack(maybeStack: unknown): maybeStack is Stack<unknown>;
+
+  /**
+   * True if `maybeSet` is a Set.
+   *
+   * Also true for OrderedSets.
+   */
+  function isSet(maybeSet: unknown): maybeSet is Set<unknown>;
+
+  /**
+   * True if `maybeOrderedSet` is an OrderedSet.
+   */
+  function isOrderedSet(
+    maybeOrderedSet: unknown
+  ): maybeOrderedSet is OrderedSet<unknown>;
+
+  /**
+   * True if `maybeRecord` is a Record.
+   */
+  function isRecord(maybeRecord: unknown): maybeRecord is Record<{}>;
+
+  /**
+   * Returns the value within the provided collection associated with the
+   * provided key, or notSetValue if the key is not defined in the collection.
+   *
+   * A functional alternative to `collection.get(key)` which will also work on
+   * plain Objects and Arrays as an alternative for `collection[key]`.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { get } = require('immutable')
+   * get([ 'dog', 'frog', 'cat' ], 2) // 'frog'
+   * get({ x: 123, y: 456 }, 'x') // 123
+   * get({ x: 123, y: 456 }, 'z', 'ifNotSet') // 'ifNotSet'
+   * ```
+   */
+  function get<K, V>(collection: Collection<K, V>, key: K): V | undefined;
+  function get<K, V, NSV>(
+    collection: Collection<K, V>,
+    key: K,
+    notSetValue: NSV
+  ): V | NSV;
+  function get<TProps extends object, K extends keyof TProps>(
+    record: Record<TProps>,
+    key: K,
+    notSetValue: unknown
+  ): TProps[K];
+  function get<V>(collection: Array<V>, key: number): V | undefined;
+  function get<V, NSV>(
+    collection: Array<V>,
+    key: number,
+    notSetValue: NSV
+  ): V | NSV;
+  function get<C extends object, K extends keyof C>(
+    object: C,
+    key: K,
+    notSetValue: unknown
+  ): C[K];
+  function get<V>(collection: { [key: string]: V }, key: string): V | undefined;
+  function get<V, NSV>(
+    collection: { [key: string]: V },
+    key: string,
+    notSetValue: NSV
+  ): V | NSV;
+
+  /**
+   * Returns true if the key is defined in the provided collection.
+   *
+   * A functional alternative to `collection.has(key)` which will also work with
+   * plain Objects and Arrays as an alternative for
+   * `collection.hasOwnProperty(key)`.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { has } = require('immutable')
+   * has([ 'dog', 'frog', 'cat' ], 2) // true
+   * has([ 'dog', 'frog', 'cat' ], 5) // false
+   * has({ x: 123, y: 456 }, 'x') // true
+   * has({ x: 123, y: 456 }, 'z') // false
+   * ```
+   */
+  function has(collection: object, key: unknown): boolean;
+
+  /**
+   * Returns a copy of the collection with the value at key removed.
+   *
+   * A functional alternative to `collection.remove(key)` which will also work
+   * with plain Objects and Arrays as an alternative for
+   * `delete collectionCopy[key]`.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { remove } = require('immutable')
+   * const originalArray = [ 'dog', 'frog', 'cat' ]
+   * remove(originalArray, 1) // [ 'dog', 'cat' ]
+   * console.log(originalArray) // [ 'dog', 'frog', 'cat' ]
+   * const originalObject = { x: 123, y: 456 }
+   * remove(originalObject, 'x') // { y: 456 }
+   * console.log(originalObject) // { x: 123, y: 456 }
+   * ```
+   */
+  function remove<K, C extends Collection<K, unknown>>(
+    collection: C,
+    key: K
+  ): C;
+  function remove<
+    TProps extends object,
+    C extends Record<TProps>,
+    K extends keyof TProps
+  >(collection: C, key: K): C;
+  function remove<C extends Array<unknown>>(collection: C, key: number): C;
+  function remove<C, K extends keyof C>(collection: C, key: K): C;
+  function remove<C extends { [key: string]: unknown }, K extends keyof C>(
+    collection: C,
+    key: K
+  ): C;
+
+  /**
+   * Returns a copy of the collection with the value at key set to the provided
+   * value.
+   *
+   * A functional alternative to `collection.set(key, value)` which will also
+   * work with plain Objects and Arrays as an alternative for
+   * `collectionCopy[key] = value`.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { set } = require('immutable')
+   * const originalArray = [ 'dog', 'frog', 'cat' ]
+   * set(originalArray, 1, 'cow') // [ 'dog', 'cow', 'cat' ]
+   * console.log(originalArray) // [ 'dog', 'frog', 'cat' ]
+   * const originalObject = { x: 123, y: 456 }
+   * set(originalObject, 'x', 789) // { x: 789, y: 456 }
+   * console.log(originalObject) // { x: 123, y: 456 }
+   * ```
+   */
+  function set<K, V, C extends Collection<K, V>>(
+    collection: C,
+    key: K,
+    value: V
+  ): C;
+  function set<
+    TProps extends object,
+    C extends Record<TProps>,
+    K extends keyof TProps
+  >(record: C, key: K, value: TProps[K]): C;
+  function set<V, C extends Array<V>>(collection: C, key: number, value: V): C;
+  function set<C, K extends keyof C>(object: C, key: K, value: C[K]): C;
+  function set<V, C extends { [key: string]: V }>(
+    collection: C,
+    key: string,
+    value: V
+  ): C;
+
+  /**
+   * Returns a copy of the collection with the value at key set to the result of
+   * providing the existing value to the updating function.
+   *
+   * A functional alternative to `collection.update(key, fn)` which will also
+   * work with plain Objects and Arrays as an alternative for
+   * `collectionCopy[key] = fn(collection[key])`.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { update } = require('immutable')
+   * const originalArray = [ 'dog', 'frog', 'cat' ]
+   * update(originalArray, 1, val => val.toUpperCase()) // [ 'dog', 'FROG', 'cat' ]
+   * console.log(originalArray) // [ 'dog', 'frog', 'cat' ]
+   * const originalObject = { x: 123, y: 456 }
+   * update(originalObject, 'x', val => val * 6) // { x: 738, y: 456 }
+   * console.log(originalObject) // { x: 123, y: 456 }
+   * ```
+   */
+  function update<K, V, C extends Collection<K, V>>(
+    collection: C,
+    key: K,
+    updater: (value: V | undefined) => V | undefined
+  ): C;
+  function update<K, V, C extends Collection<K, V>, NSV>(
+    collection: C,
+    key: K,
+    notSetValue: NSV,
+    updater: (value: V | NSV) => V
+  ): C;
+  function update<
+    TProps extends object,
+    C extends Record<TProps>,
+    K extends keyof TProps
+  >(record: C, key: K, updater: (value: TProps[K]) => TProps[K]): C;
+  function update<
+    TProps extends object,
+    C extends Record<TProps>,
+    K extends keyof TProps,
+    NSV
+  >(
+    record: C,
+    key: K,
+    notSetValue: NSV,
+    updater: (value: TProps[K] | NSV) => TProps[K]
+  ): C;
+  function update<V>(
+    collection: Array<V>,
+    key: number,
+    updater: (value: V | undefined) => V | undefined
+  ): Array<V>;
+  function update<V, NSV>(
+    collection: Array<V>,
+    key: number,
+    notSetValue: NSV,
+    updater: (value: V | NSV) => V
+  ): Array<V>;
+  function update<C, K extends keyof C>(
+    object: C,
+    key: K,
+    updater: (value: C[K]) => C[K]
+  ): C;
+  function update<C, K extends keyof C, NSV>(
+    object: C,
+    key: K,
+    notSetValue: NSV,
+    updater: (value: C[K] | NSV) => C[K]
+  ): C;
+  function update<V, C extends { [key: string]: V }, K extends keyof C>(
+    collection: C,
+    key: K,
+    updater: (value: V) => V
+  ): { [key: string]: V };
+  function update<V, C extends { [key: string]: V }, K extends keyof C, NSV>(
+    collection: C,
+    key: K,
+    notSetValue: NSV,
+    updater: (value: V | NSV) => V
+  ): { [key: string]: V };
+
+  /**
+   * Returns the value at the provided key path starting at the provided
+   * collection, or notSetValue if the key path is not defined.
+   *
+   * A functional alternative to `collection.getIn(keypath)` which will also
+   * work with plain Objects and Arrays.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { getIn } = require('immutable')
+   * getIn({ x: { y: { z: 123 }}}, ['x', 'y', 'z']) // 123
+   * getIn({ x: { y: { z: 123 }}}, ['x', 'q', 'p'], 'ifNotSet') // 'ifNotSet'
+   * ```
+   */
+  function getIn(
+    collection: unknown,
+    keyPath: Iterable<unknown>,
+    notSetValue?: unknown
+  ): unknown;
+
+  /**
+   * Returns true if the key path is defined in the provided collection.
+   *
+   * A functional alternative to `collection.hasIn(keypath)` which will also
+   * work with plain Objects and Arrays.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { hasIn } = require('immutable')
+   * hasIn({ x: { y: { z: 123 }}}, ['x', 'y', 'z']) // true
+   * hasIn({ x: { y: { z: 123 }}}, ['x', 'q', 'p']) // false
+   * ```
+   */
+  function hasIn(collection: unknown, keyPath: Iterable<unknown>): boolean;
+
+  /**
+   * Returns a copy of the collection with the value at the key path removed.
+   *
+   * A functional alternative to `collection.removeIn(keypath)` which will also
+   * work with plain Objects and Arrays.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { removeIn } = require('immutable')
+   * const original = { x: { y: { z: 123 }}}
+   * removeIn(original, ['x', 'y', 'z']) // { x: { y: {}}}
+   * console.log(original) // { x: { y: { z: 123 }}}
+   * ```
+   */
+  function removeIn<C>(collection: C, keyPath: Iterable<unknown>): C;
+
+  /**
+   * Returns a copy of the collection with the value at the key path set to the
+   * provided value.
+   *
+   * A functional alternative to `collection.setIn(keypath)` which will also
+   * work with plain Objects and Arrays.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { setIn } = require('immutable')
+   * const original = { x: { y: { z: 123 }}}
+   * setIn(original, ['x', 'y', 'z'], 456) // { x: { y: { z: 456 }}}
+   * console.log(original) // { x: { y: { z: 123 }}}
+   * ```
+   */
+  function setIn<C>(
+    collection: C,
+    keyPath: Iterable<unknown>,
+    value: unknown
+  ): C;
+
+  /**
+   * Returns a copy of the collection with the value at key path set to the
+   * result of providing the existing value to the updating function.
+   *
+   * A functional alternative to `collection.updateIn(keypath)` which will also
+   * work with plain Objects and Arrays.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { updateIn } = require('immutable')
+   * const original = { x: { y: { z: 123 }}}
+   * updateIn(original, ['x', 'y', 'z'], val => val * 6) // { x: { y: { z: 738 }}}
+   * console.log(original) // { x: { y: { z: 123 }}}
+   * ```
+   */
+  function updateIn<C>(
+    collection: C,
+    keyPath: Iterable<unknown>,
+    updater: (value: unknown) => unknown
+  ): C;
+  function updateIn<C>(
+    collection: C,
+    keyPath: Iterable<unknown>,
+    notSetValue: unknown,
+    updater: (value: unknown) => unknown
+  ): C;
+
+  /**
+   * Returns a copy of the collection with the remaining collections merged in.
+   *
+   * A functional alternative to `collection.merge()` which will also work with
+   * plain Objects and Arrays.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { merge } = require('immutable')
+   * const original = { x: 123, y: 456 }
+   * merge(original, { y: 789, z: 'abc' }) // { x: 123, y: 789, z: 'abc' }
+   * console.log(original) // { x: 123, y: 456 }
+   * ```
+   */
+  function merge<C>(
+    collection: C,
+    ...collections: Array<
+      | Iterable<unknown>
+      | Iterable<[unknown, unknown]>
+      | { [key: string]: unknown }
+    >
+  ): C;
+
+  /**
+   * Returns a copy of the collection with the remaining collections merged in,
+   * calling the `merger` function whenever an existing value is encountered.
+   *
+   * A functional alternative to `collection.mergeWith()` which will also work
+   * with plain Objects and Arrays.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { mergeWith } = require('immutable')
+   * const original = { x: 123, y: 456 }
+   * mergeWith(
+   *   (oldVal, newVal) => oldVal + newVal,
+   *   original,
+   *   { y: 789, z: 'abc' }
+   * ) // { x: 123, y: 1245, z: 'abc' }
+   * console.log(original) // { x: 123, y: 456 }
+   * ```
+   */
+  function mergeWith<C>(
+    merger: (oldVal: unknown, newVal: unknown, key: unknown) => unknown,
+    collection: C,
+    ...collections: Array<
+      | Iterable<unknown>
+      | Iterable<[unknown, unknown]>
+      | { [key: string]: unknown }
+    >
+  ): C;
+
+  /**
+   * Like `merge()`, but when two compatible collections are encountered with
+   * the same key, it merges them as well, recursing deeply through the nested
+   * data. Two collections are considered to be compatible (and thus will be
+   * merged together) if they both fall into one of three categories: keyed
+   * (e.g., `Map`s, `Record`s, and objects), indexed (e.g., `List`s and
+   * arrays), or set-like (e.g., `Set`s). If they fall into separate
+   * categories, `mergeDeep` will replace the existing collection with the
+   * collection being merged in. This behavior can be customized by using
+   * `mergeDeepWith()`.
+   *
+   * Note: Indexed and set-like collections are merged using
+   * `concat()`/`union()` and therefore do not recurse.
+   *
+   * A functional alternative to `collection.mergeDeep()` which will also work
+   * with plain Objects and Arrays.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { mergeDeep } = require('immutable')
+   * const original = { x: { y: 123 }}
+   * mergeDeep(original, { x: { z: 456 }}) // { x: { y: 123, z: 456 }}
+   * console.log(original) // { x: { y: 123 }}
+   * ```
+   */
+  function mergeDeep<C>(
+    collection: C,
+    ...collections: Array<
+      | Iterable<unknown>
+      | Iterable<[unknown, unknown]>
+      | { [key: string]: unknown }
+    >
+  ): C;
+
+  /**
+   * Like `mergeDeep()`, but when two non-collections or incompatible
+   * collections are encountered at the same key, it uses the `merger` function
+   * to determine the resulting value. Collections are considered incompatible
+   * if they fall into separate categories between keyed, indexed, and set-like.
+   *
+   * A functional alternative to `collection.mergeDeepWith()` which will also
+   * work with plain Objects and Arrays.
+   *
+   * <!-- runkit:activate -->
+   * ```js
+   * const { mergeDeepWith } = require('immutable')
+   * const original = { x: { y: 123 }}
+   * mergeDeepWith(
+   *   (oldVal, newVal) => oldVal + newVal,
+   *   original,
+   *   { x: { y: 456 }}
+   * ) // { x: { y: 579 }}
+   * console.log(original) // { x: { y: 123 }}
+   * ```
+   */
+  function mergeDeepWith<C>(
+    merger: (oldVal: unknown, newVal: unknown, key: unknown) => unknown,
+    collection: C,
+    ...collections: Array<
+      | Iterable<unknown>
+      | Iterable<[unknown, unknown]>
+      | { [key: string]: unknown }
+    >
+  ): C;
+}
+
+/**
+ * Defines the main export of the immutable module to be the Immutable namespace
+ * This supports many common module import patterns:
+ *
+ *     const Immutable = require("immutable");
+ *     const { List } = require("immutable");
+ *     import Immutable from "immutable";
+ *     import * as Immutable from "immutable";
+ *     import { List } from "immutable";
+ *
+ */
+export = Immutable;
+
+/**
+ * A global "Immutable" namespace used by UMD modules which allows the use of
+ * the full Immutable API.
+ *
+ * If using Immutable as an imported module, prefer using:
+ *
+ *     import Immutable from 'immutable'
+ *
+ */
+export as namespace Immutable;
Index: imaps-frontend/node_modules/immutable/dist/immutable.es.js
===================================================================
--- imaps-frontend/node_modules/immutable/dist/immutable.es.js	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
+++ imaps-frontend/node_modules/immutable/dist/immutable.es.js	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
@@ -0,0 +1,5936 @@
+/**
+ * @license
+ * MIT License
+ * 
+ * Copyright (c) 2014-present, Lee Byron and other contributors.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+// Used for setting prototype methods that IE8 chokes on.
+var DELETE = 'delete';
+
+// Constants describing the size of trie nodes.
+var SHIFT = 5; // Resulted in best performance after ______?
+var SIZE = 1 << SHIFT;
+var MASK = SIZE - 1;
+
+// A consistent shared value representing "not set" which equals nothing other
+// than itself, and nothing that could be provided externally.
+var NOT_SET = {};
+
+// Boolean references, Rough equivalent of `bool &`.
+function MakeRef() {
+  return { value: false };
+}
+
+function SetRef(ref) {
+  if (ref) {
+    ref.value = true;
+  }
+}
+
+// A function which returns a value representing an "owner" for transient writes
+// to tries. The return value will only ever equal itself, and will not equal
+// the return of any subsequent call of this function.
+function OwnerID() {}
+
+function ensureSize(iter) {
+  if (iter.size === undefined) {
+    iter.size = iter.__iterate(returnTrue);
+  }
+  return iter.size;
+}
+
+function wrapIndex(iter, index) {
+  // This implements "is array index" which the ECMAString spec defines as:
+  //
+  //     A String property name P is an array index if and only if
+  //     ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal
+  //     to 2^32−1.
+  //
+  // http://www.ecma-international.org/ecma-262/6.0/#sec-array-exotic-objects
+  if (typeof index !== 'number') {
+    var uint32Index = index >>> 0; // N >>> 0 is shorthand for ToUint32
+    if ('' + uint32Index !== index || uint32Index === 4294967295) {
+      return NaN;
+    }
+    index = uint32Index;
+  }
+  return index < 0 ? ensureSize(iter) + index : index;
+}
+
+function returnTrue() {
+  return true;
+}
+
+function wholeSlice(begin, end, size) {
+  return (
+    ((begin === 0 && !isNeg(begin)) ||
+      (size !== undefined && begin <= -size)) &&
+    (end === undefined || (size !== undefined && end >= size))
+  );
+}
+
+function resolveBegin(begin, size) {
+  return resolveIndex(begin, size, 0);
+}
+
+function resolveEnd(end, size) {
+  return resolveIndex(end, size, size);
+}
+
+function resolveIndex(index, size, defaultIndex) {
+  // Sanitize indices using this shorthand for ToInt32(argument)
+  // http://www.ecma-international.org/ecma-262/6.0/#sec-toint32
+  return index === undefined
+    ? defaultIndex
+    : isNeg(index)
+    ? size === Infinity
+      ? size
+      : Math.max(0, size + index) | 0
+    : size === undefined || size === index
+    ? index
+    : Math.min(size, index) | 0;
+}
+
+function isNeg(value) {
+  // Account for -0 which is negative, but not less than 0.
+  return value < 0 || (value === 0 && 1 / value === -Infinity);
+}
+
+// Note: value is unchanged to not break immutable-devtools.
+var IS_COLLECTION_SYMBOL = '@@__IMMUTABLE_ITERABLE__@@';
+
+function isCollection(maybeCollection) {
+  return Boolean(maybeCollection && maybeCollection[IS_COLLECTION_SYMBOL]);
+}
+
+var IS_KEYED_SYMBOL = '@@__IMMUTABLE_KEYED__@@';
+
+function isKeyed(maybeKeyed) {
+  return Boolean(maybeKeyed && maybeKeyed[IS_KEYED_SYMBOL]);
+}
+
+var IS_INDEXED_SYMBOL = '@@__IMMUTABLE_INDEXED__@@';
+
+function isIndexed(maybeIndexed) {
+  return Boolean(maybeIndexed && maybeIndexed[IS_INDEXED_SYMBOL]);
+}
+
+function isAssociative(maybeAssociative) {
+  return isKeyed(maybeAssociative) || isIndexed(maybeAssociative);
+}
+
+var Collection = function Collection(value) {
+  // eslint-disable-next-line no-constructor-return
+  return isCollection(value) ? value : Seq(value);
+};
+
+var KeyedCollection = /*@__PURE__*/(function (Collection) {
+  function KeyedCollection(value) {
+    // eslint-disable-next-line no-constructor-return
+    return isKeyed(value) ? value : KeyedSeq(value);
+  }
+
+  if ( Collection ) KeyedCollection.__proto__ = Collection;
+  KeyedCollection.prototype = Object.create( Collection && Collection.prototype );
+  KeyedCollection.prototype.constructor = KeyedCollection;
+
+  return KeyedCollection;
+}(Collection));
+
+var IndexedCollection = /*@__PURE__*/(function (Collection) {
+  function IndexedCollection(value) {
+    // eslint-disable-next-line no-constructor-return
+    return isIndexed(value) ? value : IndexedSeq(value);
+  }
+
+  if ( Collection ) IndexedCollection.__proto__ = Collection;
+  IndexedCollection.prototype = Object.create( Collection && Collection.prototype );
+  IndexedCollection.prototype.constructor = IndexedCollection;
+
+  return IndexedCollection;
+}(Collection));
+
+var SetCollection = /*@__PURE__*/(function (Collection) {
+  function SetCollection(value) {
+    // eslint-disable-next-line no-constructor-return
+    return isCollection(value) && !isAssociative(value) ? value : SetSeq(value);
+  }
+
+  if ( Collection ) SetCollection.__proto__ = Collection;
+  SetCollection.prototype = Object.create( Collection && Collection.prototype );
+  SetCollection.prototype.constructor = SetCollection;
+
+  return SetCollection;
+}(Collection));
+
+Collection.Keyed = KeyedCollection;
+Collection.Indexed = IndexedCollection;
+Collection.Set = SetCollection;
+
+var IS_SEQ_SYMBOL = '@@__IMMUTABLE_SEQ__@@';
+
+function isSeq(maybeSeq) {
+  return Boolean(maybeSeq && maybeSeq[IS_SEQ_SYMBOL]);
+}
+
+var IS_RECORD_SYMBOL = '@@__IMMUTABLE_RECORD__@@';
+
+function isRecord(maybeRecord) {
+  return Boolean(maybeRecord && maybeRecord[IS_RECORD_SYMBOL]);
+}
+
+function isImmutable(maybeImmutable) {
+  return isCollection(maybeImmutable) || isRecord(maybeImmutable);
+}
+
+var IS_ORDERED_SYMBOL = '@@__IMMUTABLE_ORDERED__@@';
+
+function isOrdered(maybeOrdered) {
+  return Boolean(maybeOrdered && maybeOrdered[IS_ORDERED_SYMBOL]);
+}
+
+var ITERATE_KEYS = 0;
+var ITERATE_VALUES = 1;
+var ITERATE_ENTRIES = 2;
+
+var REAL_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
+var FAUX_ITERATOR_SYMBOL = '@@iterator';
+
+var ITERATOR_SYMBOL = REAL_ITERATOR_SYMBOL || FAUX_ITERATOR_SYMBOL;
+
+var Iterator = function Iterator(next) {
+  this.next = next;
+};
+
+Iterator.prototype.toString = function toString () {
+  return '[Iterator]';
+};
+
+Iterator.KEYS = ITERATE_KEYS;
+Iterator.VALUES = ITERATE_VALUES;
+Iterator.ENTRIES = ITERATE_ENTRIES;
+
+Iterator.prototype.inspect = Iterator.prototype.toSource = function () {
+  return this.toString();
+};
+Iterator.prototype[ITERATOR_SYMBOL] = function () {
+  return this;
+};
+
+function iteratorValue(type, k, v, iteratorResult) {
+  var value = type === 0 ? k : type === 1 ? v : [k, v];
+  iteratorResult
+    ? (iteratorResult.value = value)
+    : (iteratorResult = {
+        value: value,
+        done: false,
+      });
+  return iteratorResult;
+}
+
+function iteratorDone() {
+  return { value: undefined, done: true };
+}
+
+function hasIterator(maybeIterable) {
+  if (Array.isArray(maybeIterable)) {
+    // IE11 trick as it does not support `Symbol.iterator`
+    return true;
+  }
+
+  return !!getIteratorFn(maybeIterable);
+}
+
+function isIterator(maybeIterator) {
+  return maybeIterator && typeof maybeIterator.next === 'function';
+}
+
+function getIterator(iterable) {
+  var iteratorFn = getIteratorFn(iterable);
+  return iteratorFn && iteratorFn.call(iterable);
+}
+
+function getIteratorFn(iterable) {
+  var iteratorFn =
+    iterable &&
+    ((REAL_ITERATOR_SYMBOL && iterable[REAL_ITERATOR_SYMBOL]) ||
+      iterable[FAUX_ITERATOR_SYMBOL]);
+  if (typeof iteratorFn === 'function') {
+    return iteratorFn;
+  }
+}
+
+function isEntriesIterable(maybeIterable) {
+  var iteratorFn = getIteratorFn(maybeIterable);
+  return iteratorFn && iteratorFn === maybeIterable.entries;
+}
+
+function isKeysIterable(maybeIterable) {
+  var iteratorFn = getIteratorFn(maybeIterable);
+  return iteratorFn && iteratorFn === maybeIterable.keys;
+}
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function isArrayLike(value) {
+  if (Array.isArray(value) || typeof value === 'string') {
+    return true;
+  }
+
+  return (
+    value &&
+    typeof value === 'object' &&
+    Number.isInteger(value.length) &&
+    value.length >= 0 &&
+    (value.length === 0
+      ? // Only {length: 0} is considered Array-like.
+        Object.keys(value).length === 1
+      : // An object is only Array-like if it has a property where the last value
+        // in the array-like may be found (which could be undefined).
+        value.hasOwnProperty(value.length - 1))
+  );
+}
+
+var Seq = /*@__PURE__*/(function (Collection) {
+  function Seq(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptySequence()
+      : isImmutable(value)
+      ? value.toSeq()
+      : seqFromValue(value);
+  }
+
+  if ( Collection ) Seq.__proto__ = Collection;
+  Seq.prototype = Object.create( Collection && Collection.prototype );
+  Seq.prototype.constructor = Seq;
+
+  Seq.prototype.toSeq = function toSeq () {
+    return this;
+  };
+
+  Seq.prototype.toString = function toString () {
+    return this.__toString('Seq {', '}');
+  };
+
+  Seq.prototype.cacheResult = function cacheResult () {
+    if (!this._cache && this.__iterateUncached) {
+      this._cache = this.entrySeq().toArray();
+      this.size = this._cache.length;
+    }
+    return this;
+  };
+
+  // abstract __iterateUncached(fn, reverse)
+
+  Seq.prototype.__iterate = function __iterate (fn, reverse) {
+    var cache = this._cache;
+    if (cache) {
+      var size = cache.length;
+      var i = 0;
+      while (i !== size) {
+        var entry = cache[reverse ? size - ++i : i++];
+        if (fn(entry[1], entry[0], this) === false) {
+          break;
+        }
+      }
+      return i;
+    }
+    return this.__iterateUncached(fn, reverse);
+  };
+
+  // abstract __iteratorUncached(type, reverse)
+
+  Seq.prototype.__iterator = function __iterator (type, reverse) {
+    var cache = this._cache;
+    if (cache) {
+      var size = cache.length;
+      var i = 0;
+      return new Iterator(function () {
+        if (i === size) {
+          return iteratorDone();
+        }
+        var entry = cache[reverse ? size - ++i : i++];
+        return iteratorValue(type, entry[0], entry[1]);
+      });
+    }
+    return this.__iteratorUncached(type, reverse);
+  };
+
+  return Seq;
+}(Collection));
+
+var KeyedSeq = /*@__PURE__*/(function (Seq) {
+  function KeyedSeq(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptySequence().toKeyedSeq()
+      : isCollection(value)
+      ? isKeyed(value)
+        ? value.toSeq()
+        : value.fromEntrySeq()
+      : isRecord(value)
+      ? value.toSeq()
+      : keyedSeqFromValue(value);
+  }
+
+  if ( Seq ) KeyedSeq.__proto__ = Seq;
+  KeyedSeq.prototype = Object.create( Seq && Seq.prototype );
+  KeyedSeq.prototype.constructor = KeyedSeq;
+
+  KeyedSeq.prototype.toKeyedSeq = function toKeyedSeq () {
+    return this;
+  };
+
+  return KeyedSeq;
+}(Seq));
+
+var IndexedSeq = /*@__PURE__*/(function (Seq) {
+  function IndexedSeq(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptySequence()
+      : isCollection(value)
+      ? isKeyed(value)
+        ? value.entrySeq()
+        : value.toIndexedSeq()
+      : isRecord(value)
+      ? value.toSeq().entrySeq()
+      : indexedSeqFromValue(value);
+  }
+
+  if ( Seq ) IndexedSeq.__proto__ = Seq;
+  IndexedSeq.prototype = Object.create( Seq && Seq.prototype );
+  IndexedSeq.prototype.constructor = IndexedSeq;
+
+  IndexedSeq.of = function of (/*...values*/) {
+    return IndexedSeq(arguments);
+  };
+
+  IndexedSeq.prototype.toIndexedSeq = function toIndexedSeq () {
+    return this;
+  };
+
+  IndexedSeq.prototype.toString = function toString () {
+    return this.__toString('Seq [', ']');
+  };
+
+  return IndexedSeq;
+}(Seq));
+
+var SetSeq = /*@__PURE__*/(function (Seq) {
+  function SetSeq(value) {
+    // eslint-disable-next-line no-constructor-return
+    return (
+      isCollection(value) && !isAssociative(value) ? value : IndexedSeq(value)
+    ).toSetSeq();
+  }
+
+  if ( Seq ) SetSeq.__proto__ = Seq;
+  SetSeq.prototype = Object.create( Seq && Seq.prototype );
+  SetSeq.prototype.constructor = SetSeq;
+
+  SetSeq.of = function of (/*...values*/) {
+    return SetSeq(arguments);
+  };
+
+  SetSeq.prototype.toSetSeq = function toSetSeq () {
+    return this;
+  };
+
+  return SetSeq;
+}(Seq));
+
+Seq.isSeq = isSeq;
+Seq.Keyed = KeyedSeq;
+Seq.Set = SetSeq;
+Seq.Indexed = IndexedSeq;
+
+Seq.prototype[IS_SEQ_SYMBOL] = true;
+
+// #pragma Root Sequences
+
+var ArraySeq = /*@__PURE__*/(function (IndexedSeq) {
+  function ArraySeq(array) {
+    this._array = array;
+    this.size = array.length;
+  }
+
+  if ( IndexedSeq ) ArraySeq.__proto__ = IndexedSeq;
+  ArraySeq.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+  ArraySeq.prototype.constructor = ArraySeq;
+
+  ArraySeq.prototype.get = function get (index, notSetValue) {
+    return this.has(index) ? this._array[wrapIndex(this, index)] : notSetValue;
+  };
+
+  ArraySeq.prototype.__iterate = function __iterate (fn, reverse) {
+    var array = this._array;
+    var size = array.length;
+    var i = 0;
+    while (i !== size) {
+      var ii = reverse ? size - ++i : i++;
+      if (fn(array[ii], ii, this) === false) {
+        break;
+      }
+    }
+    return i;
+  };
+
+  ArraySeq.prototype.__iterator = function __iterator (type, reverse) {
+    var array = this._array;
+    var size = array.length;
+    var i = 0;
+    return new Iterator(function () {
+      if (i === size) {
+        return iteratorDone();
+      }
+      var ii = reverse ? size - ++i : i++;
+      return iteratorValue(type, ii, array[ii]);
+    });
+  };
+
+  return ArraySeq;
+}(IndexedSeq));
+
+var ObjectSeq = /*@__PURE__*/(function (KeyedSeq) {
+  function ObjectSeq(object) {
+    var keys = Object.keys(object).concat(
+      Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols(object) : []
+    );
+    this._object = object;
+    this._keys = keys;
+    this.size = keys.length;
+  }
+
+  if ( KeyedSeq ) ObjectSeq.__proto__ = KeyedSeq;
+  ObjectSeq.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
+  ObjectSeq.prototype.constructor = ObjectSeq;
+
+  ObjectSeq.prototype.get = function get (key, notSetValue) {
+    if (notSetValue !== undefined && !this.has(key)) {
+      return notSetValue;
+    }
+    return this._object[key];
+  };
+
+  ObjectSeq.prototype.has = function has (key) {
+    return hasOwnProperty.call(this._object, key);
+  };
+
+  ObjectSeq.prototype.__iterate = function __iterate (fn, reverse) {
+    var object = this._object;
+    var keys = this._keys;
+    var size = keys.length;
+    var i = 0;
+    while (i !== size) {
+      var key = keys[reverse ? size - ++i : i++];
+      if (fn(object[key], key, this) === false) {
+        break;
+      }
+    }
+    return i;
+  };
+
+  ObjectSeq.prototype.__iterator = function __iterator (type, reverse) {
+    var object = this._object;
+    var keys = this._keys;
+    var size = keys.length;
+    var i = 0;
+    return new Iterator(function () {
+      if (i === size) {
+        return iteratorDone();
+      }
+      var key = keys[reverse ? size - ++i : i++];
+      return iteratorValue(type, key, object[key]);
+    });
+  };
+
+  return ObjectSeq;
+}(KeyedSeq));
+ObjectSeq.prototype[IS_ORDERED_SYMBOL] = true;
+
+var CollectionSeq = /*@__PURE__*/(function (IndexedSeq) {
+  function CollectionSeq(collection) {
+    this._collection = collection;
+    this.size = collection.length || collection.size;
+  }
+
+  if ( IndexedSeq ) CollectionSeq.__proto__ = IndexedSeq;
+  CollectionSeq.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+  CollectionSeq.prototype.constructor = CollectionSeq;
+
+  CollectionSeq.prototype.__iterateUncached = function __iterateUncached (fn, reverse) {
+    if (reverse) {
+      return this.cacheResult().__iterate(fn, reverse);
+    }
+    var collection = this._collection;
+    var iterator = getIterator(collection);
+    var iterations = 0;
+    if (isIterator(iterator)) {
+      var step;
+      while (!(step = iterator.next()).done) {
+        if (fn(step.value, iterations++, this) === false) {
+          break;
+        }
+      }
+    }
+    return iterations;
+  };
+
+  CollectionSeq.prototype.__iteratorUncached = function __iteratorUncached (type, reverse) {
+    if (reverse) {
+      return this.cacheResult().__iterator(type, reverse);
+    }
+    var collection = this._collection;
+    var iterator = getIterator(collection);
+    if (!isIterator(iterator)) {
+      return new Iterator(iteratorDone);
+    }
+    var iterations = 0;
+    return new Iterator(function () {
+      var step = iterator.next();
+      return step.done ? step : iteratorValue(type, iterations++, step.value);
+    });
+  };
+
+  return CollectionSeq;
+}(IndexedSeq));
+
+// # pragma Helper functions
+
+var EMPTY_SEQ;
+
+function emptySequence() {
+  return EMPTY_SEQ || (EMPTY_SEQ = new ArraySeq([]));
+}
+
+function keyedSeqFromValue(value) {
+  var seq = maybeIndexedSeqFromValue(value);
+  if (seq) {
+    return seq.fromEntrySeq();
+  }
+  if (typeof value === 'object') {
+    return new ObjectSeq(value);
+  }
+  throw new TypeError(
+    'Expected Array or collection object of [k, v] entries, or keyed object: ' +
+      value
+  );
+}
+
+function indexedSeqFromValue(value) {
+  var seq = maybeIndexedSeqFromValue(value);
+  if (seq) {
+    return seq;
+  }
+  throw new TypeError(
+    'Expected Array or collection object of values: ' + value
+  );
+}
+
+function seqFromValue(value) {
+  var seq = maybeIndexedSeqFromValue(value);
+  if (seq) {
+    return isEntriesIterable(value)
+      ? seq.fromEntrySeq()
+      : isKeysIterable(value)
+      ? seq.toSetSeq()
+      : seq;
+  }
+  if (typeof value === 'object') {
+    return new ObjectSeq(value);
+  }
+  throw new TypeError(
+    'Expected Array or collection object of values, or keyed object: ' + value
+  );
+}
+
+function maybeIndexedSeqFromValue(value) {
+  return isArrayLike(value)
+    ? new ArraySeq(value)
+    : hasIterator(value)
+    ? new CollectionSeq(value)
+    : undefined;
+}
+
+var IS_MAP_SYMBOL = '@@__IMMUTABLE_MAP__@@';
+
+function isMap(maybeMap) {
+  return Boolean(maybeMap && maybeMap[IS_MAP_SYMBOL]);
+}
+
+function isOrderedMap(maybeOrderedMap) {
+  return isMap(maybeOrderedMap) && isOrdered(maybeOrderedMap);
+}
+
+function isValueObject(maybeValue) {
+  return Boolean(
+    maybeValue &&
+      typeof maybeValue.equals === 'function' &&
+      typeof maybeValue.hashCode === 'function'
+  );
+}
+
+/**
+ * An extension of the "same-value" algorithm as [described for use by ES6 Map
+ * and Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality)
+ *
+ * NaN is considered the same as NaN, however -0 and 0 are considered the same
+ * value, which is different from the algorithm described by
+ * [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is).
+ *
+ * This is extended further to allow Objects to describe the values they
+ * represent, by way of `valueOf` or `equals` (and `hashCode`).
+ *
+ * Note: because of this extension, the key equality of Immutable.Map and the
+ * value equality of Immutable.Set will differ from ES6 Map and Set.
+ *
+ * ### Defining custom values
+ *
+ * The easiest way to describe the value an object represents is by implementing
+ * `valueOf`. For example, `Date` represents a value by returning a unix
+ * timestamp for `valueOf`:
+ *
+ *     var date1 = new Date(1234567890000); // Fri Feb 13 2009 ...
+ *     var date2 = new Date(1234567890000);
+ *     date1.valueOf(); // 1234567890000
+ *     assert( date1 !== date2 );
+ *     assert( Immutable.is( date1, date2 ) );
+ *
+ * Note: overriding `valueOf` may have other implications if you use this object
+ * where JavaScript expects a primitive, such as implicit string coercion.
+ *
+ * For more complex types, especially collections, implementing `valueOf` may
+ * not be performant. An alternative is to implement `equals` and `hashCode`.
+ *
+ * `equals` takes another object, presumably of similar type, and returns true
+ * if it is equal. Equality is symmetrical, so the same result should be
+ * returned if this and the argument are flipped.
+ *
+ *     assert( a.equals(b) === b.equals(a) );
+ *
+ * `hashCode` returns a 32bit integer number representing the object which will
+ * be used to determine how to store the value object in a Map or Set. You must
+ * provide both or neither methods, one must not exist without the other.
+ *
+ * Also, an important relationship between these methods must be upheld: if two
+ * values are equal, they *must* return the same hashCode. If the values are not
+ * equal, they might have the same hashCode; this is called a hash collision,
+ * and while undesirable for performance reasons, it is acceptable.
+ *
+ *     if (a.equals(b)) {
+ *       assert( a.hashCode() === b.hashCode() );
+ *     }
+ *
+ * All Immutable collections are Value Objects: they implement `equals()`
+ * and `hashCode()`.
+ */
+function is(valueA, valueB) {
+  if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {
+    return true;
+  }
+  if (!valueA || !valueB) {
+    return false;
+  }
+  if (
+    typeof valueA.valueOf === 'function' &&
+    typeof valueB.valueOf === 'function'
+  ) {
+    valueA = valueA.valueOf();
+    valueB = valueB.valueOf();
+    if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {
+      return true;
+    }
+    if (!valueA || !valueB) {
+      return false;
+    }
+  }
+  return !!(
+    isValueObject(valueA) &&
+    isValueObject(valueB) &&
+    valueA.equals(valueB)
+  );
+}
+
+var imul =
+  typeof Math.imul === 'function' && Math.imul(0xffffffff, 2) === -2
+    ? Math.imul
+    : function imul(a, b) {
+        a |= 0; // int
+        b |= 0; // int
+        var c = a & 0xffff;
+        var d = b & 0xffff;
+        // Shift by 0 fixes the sign on the high part.
+        return (c * d + ((((a >>> 16) * d + c * (b >>> 16)) << 16) >>> 0)) | 0; // int
+      };
+
+// v8 has an optimization for storing 31-bit signed numbers.
+// Values which have either 00 or 11 as the high order bits qualify.
+// This function drops the highest order bit in a signed number, maintaining
+// the sign bit.
+function smi(i32) {
+  return ((i32 >>> 1) & 0x40000000) | (i32 & 0xbfffffff);
+}
+
+var defaultValueOf = Object.prototype.valueOf;
+
+function hash(o) {
+  if (o == null) {
+    return hashNullish(o);
+  }
+
+  if (typeof o.hashCode === 'function') {
+    // Drop any high bits from accidentally long hash codes.
+    return smi(o.hashCode(o));
+  }
+
+  var v = valueOf(o);
+
+  if (v == null) {
+    return hashNullish(v);
+  }
+
+  switch (typeof v) {
+    case 'boolean':
+      // The hash values for built-in constants are a 1 value for each 5-byte
+      // shift region expect for the first, which encodes the value. This
+      // reduces the odds of a hash collision for these common values.
+      return v ? 0x42108421 : 0x42108420;
+    case 'number':
+      return hashNumber(v);
+    case 'string':
+      return v.length > STRING_HASH_CACHE_MIN_STRLEN
+        ? cachedHashString(v)
+        : hashString(v);
+    case 'object':
+    case 'function':
+      return hashJSObj(v);
+    case 'symbol':
+      return hashSymbol(v);
+    default:
+      if (typeof v.toString === 'function') {
+        return hashString(v.toString());
+      }
+      throw new Error('Value type ' + typeof v + ' cannot be hashed.');
+  }
+}
+
+function hashNullish(nullish) {
+  return nullish === null ? 0x42108422 : /* undefined */ 0x42108423;
+}
+
+// Compress arbitrarily large numbers into smi hashes.
+function hashNumber(n) {
+  if (n !== n || n === Infinity) {
+    return 0;
+  }
+  var hash = n | 0;
+  if (hash !== n) {
+    hash ^= n * 0xffffffff;
+  }
+  while (n > 0xffffffff) {
+    n /= 0xffffffff;
+    hash ^= n;
+  }
+  return smi(hash);
+}
+
+function cachedHashString(string) {
+  var hashed = stringHashCache[string];
+  if (hashed === undefined) {
+    hashed = hashString(string);
+    if (STRING_HASH_CACHE_SIZE === STRING_HASH_CACHE_MAX_SIZE) {
+      STRING_HASH_CACHE_SIZE = 0;
+      stringHashCache = {};
+    }
+    STRING_HASH_CACHE_SIZE++;
+    stringHashCache[string] = hashed;
+  }
+  return hashed;
+}
+
+// http://jsperf.com/hashing-strings
+function hashString(string) {
+  // This is the hash from JVM
+  // The hash code for a string is computed as
+  // s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1],
+  // where s[i] is the ith character of the string and n is the length of
+  // the string. We "mod" the result to make it between 0 (inclusive) and 2^31
+  // (exclusive) by dropping high bits.
+  var hashed = 0;
+  for (var ii = 0; ii < string.length; ii++) {
+    hashed = (31 * hashed + string.charCodeAt(ii)) | 0;
+  }
+  return smi(hashed);
+}
+
+function hashSymbol(sym) {
+  var hashed = symbolMap[sym];
+  if (hashed !== undefined) {
+    return hashed;
+  }
+
+  hashed = nextHash();
+
+  symbolMap[sym] = hashed;
+
+  return hashed;
+}
+
+function hashJSObj(obj) {
+  var hashed;
+  if (usingWeakMap) {
+    hashed = weakMap.get(obj);
+    if (hashed !== undefined) {
+      return hashed;
+    }
+  }
+
+  hashed = obj[UID_HASH_KEY];
+  if (hashed !== undefined) {
+    return hashed;
+  }
+
+  if (!canDefineProperty) {
+    hashed = obj.propertyIsEnumerable && obj.propertyIsEnumerable[UID_HASH_KEY];
+    if (hashed !== undefined) {
+      return hashed;
+    }
+
+    hashed = getIENodeHash(obj);
+    if (hashed !== undefined) {
+      return hashed;
+    }
+  }
+
+  hashed = nextHash();
+
+  if (usingWeakMap) {
+    weakMap.set(obj, hashed);
+  } else if (isExtensible !== undefined && isExtensible(obj) === false) {
+    throw new Error('Non-extensible objects are not allowed as keys.');
+  } else if (canDefineProperty) {
+    Object.defineProperty(obj, UID_HASH_KEY, {
+      enumerable: false,
+      configurable: false,
+      writable: false,
+      value: hashed,
+    });
+  } else if (
+    obj.propertyIsEnumerable !== undefined &&
+    obj.propertyIsEnumerable === obj.constructor.prototype.propertyIsEnumerable
+  ) {
+    // Since we can't define a non-enumerable property on the object
+    // we'll hijack one of the less-used non-enumerable properties to
+    // save our hash on it. Since this is a function it will not show up in
+    // `JSON.stringify` which is what we want.
+    obj.propertyIsEnumerable = function () {
+      return this.constructor.prototype.propertyIsEnumerable.apply(
+        this,
+        arguments
+      );
+    };
+    obj.propertyIsEnumerable[UID_HASH_KEY] = hashed;
+  } else if (obj.nodeType !== undefined) {
+    // At this point we couldn't get the IE `uniqueID` to use as a hash
+    // and we couldn't use a non-enumerable property to exploit the
+    // dontEnum bug so we simply add the `UID_HASH_KEY` on the node
+    // itself.
+    obj[UID_HASH_KEY] = hashed;
+  } else {
+    throw new Error('Unable to set a non-enumerable property on object.');
+  }
+
+  return hashed;
+}
+
+// Get references to ES5 object methods.
+var isExtensible = Object.isExtensible;
+
+// True if Object.defineProperty works as expected. IE8 fails this test.
+var canDefineProperty = (function () {
+  try {
+    Object.defineProperty({}, '@', {});
+    return true;
+  } catch (e) {
+    return false;
+  }
+})();
+
+// IE has a `uniqueID` property on DOM nodes. We can construct the hash from it
+// and avoid memory leaks from the IE cloneNode bug.
+function getIENodeHash(node) {
+  if (node && node.nodeType > 0) {
+    switch (node.nodeType) {
+      case 1: // Element
+        return node.uniqueID;
+      case 9: // Document
+        return node.documentElement && node.documentElement.uniqueID;
+    }
+  }
+}
+
+function valueOf(obj) {
+  return obj.valueOf !== defaultValueOf && typeof obj.valueOf === 'function'
+    ? obj.valueOf(obj)
+    : obj;
+}
+
+function nextHash() {
+  var nextHash = ++_objHashUID;
+  if (_objHashUID & 0x40000000) {
+    _objHashUID = 0;
+  }
+  return nextHash;
+}
+
+// If possible, use a WeakMap.
+var usingWeakMap = typeof WeakMap === 'function';
+var weakMap;
+if (usingWeakMap) {
+  weakMap = new WeakMap();
+}
+
+var symbolMap = Object.create(null);
+
+var _objHashUID = 0;
+
+var UID_HASH_KEY = '__immutablehash__';
+if (typeof Symbol === 'function') {
+  UID_HASH_KEY = Symbol(UID_HASH_KEY);
+}
+
+var STRING_HASH_CACHE_MIN_STRLEN = 16;
+var STRING_HASH_CACHE_MAX_SIZE = 255;
+var STRING_HASH_CACHE_SIZE = 0;
+var stringHashCache = {};
+
+var ToKeyedSequence = /*@__PURE__*/(function (KeyedSeq) {
+  function ToKeyedSequence(indexed, useKeys) {
+    this._iter = indexed;
+    this._useKeys = useKeys;
+    this.size = indexed.size;
+  }
+
+  if ( KeyedSeq ) ToKeyedSequence.__proto__ = KeyedSeq;
+  ToKeyedSequence.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
+  ToKeyedSequence.prototype.constructor = ToKeyedSequence;
+
+  ToKeyedSequence.prototype.get = function get (key, notSetValue) {
+    return this._iter.get(key, notSetValue);
+  };
+
+  ToKeyedSequence.prototype.has = function has (key) {
+    return this._iter.has(key);
+  };
+
+  ToKeyedSequence.prototype.valueSeq = function valueSeq () {
+    return this._iter.valueSeq();
+  };
+
+  ToKeyedSequence.prototype.reverse = function reverse () {
+    var this$1$1 = this;
+
+    var reversedSequence = reverseFactory(this, true);
+    if (!this._useKeys) {
+      reversedSequence.valueSeq = function () { return this$1$1._iter.toSeq().reverse(); };
+    }
+    return reversedSequence;
+  };
+
+  ToKeyedSequence.prototype.map = function map (mapper, context) {
+    var this$1$1 = this;
+
+    var mappedSequence = mapFactory(this, mapper, context);
+    if (!this._useKeys) {
+      mappedSequence.valueSeq = function () { return this$1$1._iter.toSeq().map(mapper, context); };
+    }
+    return mappedSequence;
+  };
+
+  ToKeyedSequence.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    return this._iter.__iterate(function (v, k) { return fn(v, k, this$1$1); }, reverse);
+  };
+
+  ToKeyedSequence.prototype.__iterator = function __iterator (type, reverse) {
+    return this._iter.__iterator(type, reverse);
+  };
+
+  return ToKeyedSequence;
+}(KeyedSeq));
+ToKeyedSequence.prototype[IS_ORDERED_SYMBOL] = true;
+
+var ToIndexedSequence = /*@__PURE__*/(function (IndexedSeq) {
+  function ToIndexedSequence(iter) {
+    this._iter = iter;
+    this.size = iter.size;
+  }
+
+  if ( IndexedSeq ) ToIndexedSequence.__proto__ = IndexedSeq;
+  ToIndexedSequence.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+  ToIndexedSequence.prototype.constructor = ToIndexedSequence;
+
+  ToIndexedSequence.prototype.includes = function includes (value) {
+    return this._iter.includes(value);
+  };
+
+  ToIndexedSequence.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    var i = 0;
+    reverse && ensureSize(this);
+    return this._iter.__iterate(
+      function (v) { return fn(v, reverse ? this$1$1.size - ++i : i++, this$1$1); },
+      reverse
+    );
+  };
+
+  ToIndexedSequence.prototype.__iterator = function __iterator (type, reverse) {
+    var this$1$1 = this;
+
+    var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
+    var i = 0;
+    reverse && ensureSize(this);
+    return new Iterator(function () {
+      var step = iterator.next();
+      return step.done
+        ? step
+        : iteratorValue(
+            type,
+            reverse ? this$1$1.size - ++i : i++,
+            step.value,
+            step
+          );
+    });
+  };
+
+  return ToIndexedSequence;
+}(IndexedSeq));
+
+var ToSetSequence = /*@__PURE__*/(function (SetSeq) {
+  function ToSetSequence(iter) {
+    this._iter = iter;
+    this.size = iter.size;
+  }
+
+  if ( SetSeq ) ToSetSequence.__proto__ = SetSeq;
+  ToSetSequence.prototype = Object.create( SetSeq && SetSeq.prototype );
+  ToSetSequence.prototype.constructor = ToSetSequence;
+
+  ToSetSequence.prototype.has = function has (key) {
+    return this._iter.includes(key);
+  };
+
+  ToSetSequence.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    return this._iter.__iterate(function (v) { return fn(v, v, this$1$1); }, reverse);
+  };
+
+  ToSetSequence.prototype.__iterator = function __iterator (type, reverse) {
+    var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
+    return new Iterator(function () {
+      var step = iterator.next();
+      return step.done
+        ? step
+        : iteratorValue(type, step.value, step.value, step);
+    });
+  };
+
+  return ToSetSequence;
+}(SetSeq));
+
+var FromEntriesSequence = /*@__PURE__*/(function (KeyedSeq) {
+  function FromEntriesSequence(entries) {
+    this._iter = entries;
+    this.size = entries.size;
+  }
+
+  if ( KeyedSeq ) FromEntriesSequence.__proto__ = KeyedSeq;
+  FromEntriesSequence.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
+  FromEntriesSequence.prototype.constructor = FromEntriesSequence;
+
+  FromEntriesSequence.prototype.entrySeq = function entrySeq () {
+    return this._iter.toSeq();
+  };
+
+  FromEntriesSequence.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    return this._iter.__iterate(function (entry) {
+      // Check if entry exists first so array access doesn't throw for holes
+      // in the parent iteration.
+      if (entry) {
+        validateEntry(entry);
+        var indexedCollection = isCollection(entry);
+        return fn(
+          indexedCollection ? entry.get(1) : entry[1],
+          indexedCollection ? entry.get(0) : entry[0],
+          this$1$1
+        );
+      }
+    }, reverse);
+  };
+
+  FromEntriesSequence.prototype.__iterator = function __iterator (type, reverse) {
+    var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
+    return new Iterator(function () {
+      while (true) {
+        var step = iterator.next();
+        if (step.done) {
+          return step;
+        }
+        var entry = step.value;
+        // Check if entry exists first so array access doesn't throw for holes
+        // in the parent iteration.
+        if (entry) {
+          validateEntry(entry);
+          var indexedCollection = isCollection(entry);
+          return iteratorValue(
+            type,
+            indexedCollection ? entry.get(0) : entry[0],
+            indexedCollection ? entry.get(1) : entry[1],
+            step
+          );
+        }
+      }
+    });
+  };
+
+  return FromEntriesSequence;
+}(KeyedSeq));
+
+ToIndexedSequence.prototype.cacheResult =
+  ToKeyedSequence.prototype.cacheResult =
+  ToSetSequence.prototype.cacheResult =
+  FromEntriesSequence.prototype.cacheResult =
+    cacheResultThrough;
+
+function flipFactory(collection) {
+  var flipSequence = makeSequence(collection);
+  flipSequence._iter = collection;
+  flipSequence.size = collection.size;
+  flipSequence.flip = function () { return collection; };
+  flipSequence.reverse = function () {
+    var reversedSequence = collection.reverse.apply(this); // super.reverse()
+    reversedSequence.flip = function () { return collection.reverse(); };
+    return reversedSequence;
+  };
+  flipSequence.has = function (key) { return collection.includes(key); };
+  flipSequence.includes = function (key) { return collection.has(key); };
+  flipSequence.cacheResult = cacheResultThrough;
+  flipSequence.__iterateUncached = function (fn, reverse) {
+    var this$1$1 = this;
+
+    return collection.__iterate(function (v, k) { return fn(k, v, this$1$1) !== false; }, reverse);
+  };
+  flipSequence.__iteratorUncached = function (type, reverse) {
+    if (type === ITERATE_ENTRIES) {
+      var iterator = collection.__iterator(type, reverse);
+      return new Iterator(function () {
+        var step = iterator.next();
+        if (!step.done) {
+          var k = step.value[0];
+          step.value[0] = step.value[1];
+          step.value[1] = k;
+        }
+        return step;
+      });
+    }
+    return collection.__iterator(
+      type === ITERATE_VALUES ? ITERATE_KEYS : ITERATE_VALUES,
+      reverse
+    );
+  };
+  return flipSequence;
+}
+
+function mapFactory(collection, mapper, context) {
+  var mappedSequence = makeSequence(collection);
+  mappedSequence.size = collection.size;
+  mappedSequence.has = function (key) { return collection.has(key); };
+  mappedSequence.get = function (key, notSetValue) {
+    var v = collection.get(key, NOT_SET);
+    return v === NOT_SET
+      ? notSetValue
+      : mapper.call(context, v, key, collection);
+  };
+  mappedSequence.__iterateUncached = function (fn, reverse) {
+    var this$1$1 = this;
+
+    return collection.__iterate(
+      function (v, k, c) { return fn(mapper.call(context, v, k, c), k, this$1$1) !== false; },
+      reverse
+    );
+  };
+  mappedSequence.__iteratorUncached = function (type, reverse) {
+    var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+    return new Iterator(function () {
+      var step = iterator.next();
+      if (step.done) {
+        return step;
+      }
+      var entry = step.value;
+      var key = entry[0];
+      return iteratorValue(
+        type,
+        key,
+        mapper.call(context, entry[1], key, collection),
+        step
+      );
+    });
+  };
+  return mappedSequence;
+}
+
+function reverseFactory(collection, useKeys) {
+  var this$1$1 = this;
+
+  var reversedSequence = makeSequence(collection);
+  reversedSequence._iter = collection;
+  reversedSequence.size = collection.size;
+  reversedSequence.reverse = function () { return collection; };
+  if (collection.flip) {
+    reversedSequence.flip = function () {
+      var flipSequence = flipFactory(collection);
+      flipSequence.reverse = function () { return collection.flip(); };
+      return flipSequence;
+    };
+  }
+  reversedSequence.get = function (key, notSetValue) { return collection.get(useKeys ? key : -1 - key, notSetValue); };
+  reversedSequence.has = function (key) { return collection.has(useKeys ? key : -1 - key); };
+  reversedSequence.includes = function (value) { return collection.includes(value); };
+  reversedSequence.cacheResult = cacheResultThrough;
+  reversedSequence.__iterate = function (fn, reverse) {
+    var this$1$1 = this;
+
+    var i = 0;
+    reverse && ensureSize(collection);
+    return collection.__iterate(
+      function (v, k) { return fn(v, useKeys ? k : reverse ? this$1$1.size - ++i : i++, this$1$1); },
+      !reverse
+    );
+  };
+  reversedSequence.__iterator = function (type, reverse) {
+    var i = 0;
+    reverse && ensureSize(collection);
+    var iterator = collection.__iterator(ITERATE_ENTRIES, !reverse);
+    return new Iterator(function () {
+      var step = iterator.next();
+      if (step.done) {
+        return step;
+      }
+      var entry = step.value;
+      return iteratorValue(
+        type,
+        useKeys ? entry[0] : reverse ? this$1$1.size - ++i : i++,
+        entry[1],
+        step
+      );
+    });
+  };
+  return reversedSequence;
+}
+
+function filterFactory(collection, predicate, context, useKeys) {
+  var filterSequence = makeSequence(collection);
+  if (useKeys) {
+    filterSequence.has = function (key) {
+      var v = collection.get(key, NOT_SET);
+      return v !== NOT_SET && !!predicate.call(context, v, key, collection);
+    };
+    filterSequence.get = function (key, notSetValue) {
+      var v = collection.get(key, NOT_SET);
+      return v !== NOT_SET && predicate.call(context, v, key, collection)
+        ? v
+        : notSetValue;
+    };
+  }
+  filterSequence.__iterateUncached = function (fn, reverse) {
+    var this$1$1 = this;
+
+    var iterations = 0;
+    collection.__iterate(function (v, k, c) {
+      if (predicate.call(context, v, k, c)) {
+        iterations++;
+        return fn(v, useKeys ? k : iterations - 1, this$1$1);
+      }
+    }, reverse);
+    return iterations;
+  };
+  filterSequence.__iteratorUncached = function (type, reverse) {
+    var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+    var iterations = 0;
+    return new Iterator(function () {
+      while (true) {
+        var step = iterator.next();
+        if (step.done) {
+          return step;
+        }
+        var entry = step.value;
+        var key = entry[0];
+        var value = entry[1];
+        if (predicate.call(context, value, key, collection)) {
+          return iteratorValue(type, useKeys ? key : iterations++, value, step);
+        }
+      }
+    });
+  };
+  return filterSequence;
+}
+
+function countByFactory(collection, grouper, context) {
+  var groups = Map().asMutable();
+  collection.__iterate(function (v, k) {
+    groups.update(grouper.call(context, v, k, collection), 0, function (a) { return a + 1; });
+  });
+  return groups.asImmutable();
+}
+
+function groupByFactory(collection, grouper, context) {
+  var isKeyedIter = isKeyed(collection);
+  var groups = (isOrdered(collection) ? OrderedMap() : Map()).asMutable();
+  collection.__iterate(function (v, k) {
+    groups.update(
+      grouper.call(context, v, k, collection),
+      function (a) { return ((a = a || []), a.push(isKeyedIter ? [k, v] : v), a); }
+    );
+  });
+  var coerce = collectionClass(collection);
+  return groups.map(function (arr) { return reify(collection, coerce(arr)); }).asImmutable();
+}
+
+function partitionFactory(collection, predicate, context) {
+  var isKeyedIter = isKeyed(collection);
+  var groups = [[], []];
+  collection.__iterate(function (v, k) {
+    groups[predicate.call(context, v, k, collection) ? 1 : 0].push(
+      isKeyedIter ? [k, v] : v
+    );
+  });
+  var coerce = collectionClass(collection);
+  return groups.map(function (arr) { return reify(collection, coerce(arr)); });
+}
+
+function sliceFactory(collection, begin, end, useKeys) {
+  var originalSize = collection.size;
+
+  if (wholeSlice(begin, end, originalSize)) {
+    return collection;
+  }
+
+  // begin or end can not be resolved if they were provided as negative numbers and
+  // this collection's size is unknown. In that case, cache first so there is
+  // a known size and these do not resolve to NaN.
+  if (typeof originalSize === 'undefined' && (begin < 0 || end < 0)) {
+    return sliceFactory(collection.toSeq().cacheResult(), begin, end, useKeys);
+  }
+
+  var resolvedBegin = resolveBegin(begin, originalSize);
+  var resolvedEnd = resolveEnd(end, originalSize);
+
+  // Note: resolvedEnd is undefined when the original sequence's length is
+  // unknown and this slice did not supply an end and should contain all
+  // elements after resolvedBegin.
+  // In that case, resolvedSize will be NaN and sliceSize will remain undefined.
+  var resolvedSize = resolvedEnd - resolvedBegin;
+  var sliceSize;
+  if (resolvedSize === resolvedSize) {
+    sliceSize = resolvedSize < 0 ? 0 : resolvedSize;
+  }
+
+  var sliceSeq = makeSequence(collection);
+
+  // If collection.size is undefined, the size of the realized sliceSeq is
+  // unknown at this point unless the number of items to slice is 0
+  sliceSeq.size =
+    sliceSize === 0 ? sliceSize : (collection.size && sliceSize) || undefined;
+
+  if (!useKeys && isSeq(collection) && sliceSize >= 0) {
+    sliceSeq.get = function (index, notSetValue) {
+      index = wrapIndex(this, index);
+      return index >= 0 && index < sliceSize
+        ? collection.get(index + resolvedBegin, notSetValue)
+        : notSetValue;
+    };
+  }
+
+  sliceSeq.__iterateUncached = function (fn, reverse) {
+    var this$1$1 = this;
+
+    if (sliceSize === 0) {
+      return 0;
+    }
+    if (reverse) {
+      return this.cacheResult().__iterate(fn, reverse);
+    }
+    var skipped = 0;
+    var isSkipping = true;
+    var iterations = 0;
+    collection.__iterate(function (v, k) {
+      if (!(isSkipping && (isSkipping = skipped++ < resolvedBegin))) {
+        iterations++;
+        return (
+          fn(v, useKeys ? k : iterations - 1, this$1$1) !== false &&
+          iterations !== sliceSize
+        );
+      }
+    });
+    return iterations;
+  };
+
+  sliceSeq.__iteratorUncached = function (type, reverse) {
+    if (sliceSize !== 0 && reverse) {
+      return this.cacheResult().__iterator(type, reverse);
+    }
+    // Don't bother instantiating parent iterator if taking 0.
+    if (sliceSize === 0) {
+      return new Iterator(iteratorDone);
+    }
+    var iterator = collection.__iterator(type, reverse);
+    var skipped = 0;
+    var iterations = 0;
+    return new Iterator(function () {
+      while (skipped++ < resolvedBegin) {
+        iterator.next();
+      }
+      if (++iterations > sliceSize) {
+        return iteratorDone();
+      }
+      var step = iterator.next();
+      if (useKeys || type === ITERATE_VALUES || step.done) {
+        return step;
+      }
+      if (type === ITERATE_KEYS) {
+        return iteratorValue(type, iterations - 1, undefined, step);
+      }
+      return iteratorValue(type, iterations - 1, step.value[1], step);
+    });
+  };
+
+  return sliceSeq;
+}
+
+function takeWhileFactory(collection, predicate, context) {
+  var takeSequence = makeSequence(collection);
+  takeSequence.__iterateUncached = function (fn, reverse) {
+    var this$1$1 = this;
+
+    if (reverse) {
+      return this.cacheResult().__iterate(fn, reverse);
+    }
+    var iterations = 0;
+    collection.__iterate(
+      function (v, k, c) { return predicate.call(context, v, k, c) && ++iterations && fn(v, k, this$1$1); }
+    );
+    return iterations;
+  };
+  takeSequence.__iteratorUncached = function (type, reverse) {
+    var this$1$1 = this;
+
+    if (reverse) {
+      return this.cacheResult().__iterator(type, reverse);
+    }
+    var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+    var iterating = true;
+    return new Iterator(function () {
+      if (!iterating) {
+        return iteratorDone();
+      }
+      var step = iterator.next();
+      if (step.done) {
+        return step;
+      }
+      var entry = step.value;
+      var k = entry[0];
+      var v = entry[1];
+      if (!predicate.call(context, v, k, this$1$1)) {
+        iterating = false;
+        return iteratorDone();
+      }
+      return type === ITERATE_ENTRIES ? step : iteratorValue(type, k, v, step);
+    });
+  };
+  return takeSequence;
+}
+
+function skipWhileFactory(collection, predicate, context, useKeys) {
+  var skipSequence = makeSequence(collection);
+  skipSequence.__iterateUncached = function (fn, reverse) {
+    var this$1$1 = this;
+
+    if (reverse) {
+      return this.cacheResult().__iterate(fn, reverse);
+    }
+    var isSkipping = true;
+    var iterations = 0;
+    collection.__iterate(function (v, k, c) {
+      if (!(isSkipping && (isSkipping = predicate.call(context, v, k, c)))) {
+        iterations++;
+        return fn(v, useKeys ? k : iterations - 1, this$1$1);
+      }
+    });
+    return iterations;
+  };
+  skipSequence.__iteratorUncached = function (type, reverse) {
+    var this$1$1 = this;
+
+    if (reverse) {
+      return this.cacheResult().__iterator(type, reverse);
+    }
+    var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+    var skipping = true;
+    var iterations = 0;
+    return new Iterator(function () {
+      var step;
+      var k;
+      var v;
+      do {
+        step = iterator.next();
+        if (step.done) {
+          if (useKeys || type === ITERATE_VALUES) {
+            return step;
+          }
+          if (type === ITERATE_KEYS) {
+            return iteratorValue(type, iterations++, undefined, step);
+          }
+          return iteratorValue(type, iterations++, step.value[1], step);
+        }
+        var entry = step.value;
+        k = entry[0];
+        v = entry[1];
+        skipping && (skipping = predicate.call(context, v, k, this$1$1));
+      } while (skipping);
+      return type === ITERATE_ENTRIES ? step : iteratorValue(type, k, v, step);
+    });
+  };
+  return skipSequence;
+}
+
+function concatFactory(collection, values) {
+  var isKeyedCollection = isKeyed(collection);
+  var iters = [collection]
+    .concat(values)
+    .map(function (v) {
+      if (!isCollection(v)) {
+        v = isKeyedCollection
+          ? keyedSeqFromValue(v)
+          : indexedSeqFromValue(Array.isArray(v) ? v : [v]);
+      } else if (isKeyedCollection) {
+        v = KeyedCollection(v);
+      }
+      return v;
+    })
+    .filter(function (v) { return v.size !== 0; });
+
+  if (iters.length === 0) {
+    return collection;
+  }
+
+  if (iters.length === 1) {
+    var singleton = iters[0];
+    if (
+      singleton === collection ||
+      (isKeyedCollection && isKeyed(singleton)) ||
+      (isIndexed(collection) && isIndexed(singleton))
+    ) {
+      return singleton;
+    }
+  }
+
+  var concatSeq = new ArraySeq(iters);
+  if (isKeyedCollection) {
+    concatSeq = concatSeq.toKeyedSeq();
+  } else if (!isIndexed(collection)) {
+    concatSeq = concatSeq.toSetSeq();
+  }
+  concatSeq = concatSeq.flatten(true);
+  concatSeq.size = iters.reduce(function (sum, seq) {
+    if (sum !== undefined) {
+      var size = seq.size;
+      if (size !== undefined) {
+        return sum + size;
+      }
+    }
+  }, 0);
+  return concatSeq;
+}
+
+function flattenFactory(collection, depth, useKeys) {
+  var flatSequence = makeSequence(collection);
+  flatSequence.__iterateUncached = function (fn, reverse) {
+    if (reverse) {
+      return this.cacheResult().__iterate(fn, reverse);
+    }
+    var iterations = 0;
+    var stopped = false;
+    function flatDeep(iter, currentDepth) {
+      iter.__iterate(function (v, k) {
+        if ((!depth || currentDepth < depth) && isCollection(v)) {
+          flatDeep(v, currentDepth + 1);
+        } else {
+          iterations++;
+          if (fn(v, useKeys ? k : iterations - 1, flatSequence) === false) {
+            stopped = true;
+          }
+        }
+        return !stopped;
+      }, reverse);
+    }
+    flatDeep(collection, 0);
+    return iterations;
+  };
+  flatSequence.__iteratorUncached = function (type, reverse) {
+    if (reverse) {
+      return this.cacheResult().__iterator(type, reverse);
+    }
+    var iterator = collection.__iterator(type, reverse);
+    var stack = [];
+    var iterations = 0;
+    return new Iterator(function () {
+      while (iterator) {
+        var step = iterator.next();
+        if (step.done !== false) {
+          iterator = stack.pop();
+          continue;
+        }
+        var v = step.value;
+        if (type === ITERATE_ENTRIES) {
+          v = v[1];
+        }
+        if ((!depth || stack.length < depth) && isCollection(v)) {
+          stack.push(iterator);
+          iterator = v.__iterator(type, reverse);
+        } else {
+          return useKeys ? step : iteratorValue(type, iterations++, v, step);
+        }
+      }
+      return iteratorDone();
+    });
+  };
+  return flatSequence;
+}
+
+function flatMapFactory(collection, mapper, context) {
+  var coerce = collectionClass(collection);
+  return collection
+    .toSeq()
+    .map(function (v, k) { return coerce(mapper.call(context, v, k, collection)); })
+    .flatten(true);
+}
+
+function interposeFactory(collection, separator) {
+  var interposedSequence = makeSequence(collection);
+  interposedSequence.size = collection.size && collection.size * 2 - 1;
+  interposedSequence.__iterateUncached = function (fn, reverse) {
+    var this$1$1 = this;
+
+    var iterations = 0;
+    collection.__iterate(
+      function (v) { return (!iterations || fn(separator, iterations++, this$1$1) !== false) &&
+        fn(v, iterations++, this$1$1) !== false; },
+      reverse
+    );
+    return iterations;
+  };
+  interposedSequence.__iteratorUncached = function (type, reverse) {
+    var iterator = collection.__iterator(ITERATE_VALUES, reverse);
+    var iterations = 0;
+    var step;
+    return new Iterator(function () {
+      if (!step || iterations % 2) {
+        step = iterator.next();
+        if (step.done) {
+          return step;
+        }
+      }
+      return iterations % 2
+        ? iteratorValue(type, iterations++, separator)
+        : iteratorValue(type, iterations++, step.value, step);
+    });
+  };
+  return interposedSequence;
+}
+
+function sortFactory(collection, comparator, mapper) {
+  if (!comparator) {
+    comparator = defaultComparator;
+  }
+  var isKeyedCollection = isKeyed(collection);
+  var index = 0;
+  var entries = collection
+    .toSeq()
+    .map(function (v, k) { return [k, v, index++, mapper ? mapper(v, k, collection) : v]; })
+    .valueSeq()
+    .toArray();
+  entries
+    .sort(function (a, b) { return comparator(a[3], b[3]) || a[2] - b[2]; })
+    .forEach(
+      isKeyedCollection
+        ? function (v, i) {
+            entries[i].length = 2;
+          }
+        : function (v, i) {
+            entries[i] = v[1];
+          }
+    );
+  return isKeyedCollection
+    ? KeyedSeq(entries)
+    : isIndexed(collection)
+    ? IndexedSeq(entries)
+    : SetSeq(entries);
+}
+
+function maxFactory(collection, comparator, mapper) {
+  if (!comparator) {
+    comparator = defaultComparator;
+  }
+  if (mapper) {
+    var entry = collection
+      .toSeq()
+      .map(function (v, k) { return [v, mapper(v, k, collection)]; })
+      .reduce(function (a, b) { return (maxCompare(comparator, a[1], b[1]) ? b : a); });
+    return entry && entry[0];
+  }
+  return collection.reduce(function (a, b) { return (maxCompare(comparator, a, b) ? b : a); });
+}
+
+function maxCompare(comparator, a, b) {
+  var comp = comparator(b, a);
+  // b is considered the new max if the comparator declares them equal, but
+  // they are not equal and b is in fact a nullish value.
+  return (
+    (comp === 0 && b !== a && (b === undefined || b === null || b !== b)) ||
+    comp > 0
+  );
+}
+
+function zipWithFactory(keyIter, zipper, iters, zipAll) {
+  var zipSequence = makeSequence(keyIter);
+  var sizes = new ArraySeq(iters).map(function (i) { return i.size; });
+  zipSequence.size = zipAll ? sizes.max() : sizes.min();
+  // Note: this a generic base implementation of __iterate in terms of
+  // __iterator which may be more generically useful in the future.
+  zipSequence.__iterate = function (fn, reverse) {
+    /* generic:
+    var iterator = this.__iterator(ITERATE_ENTRIES, reverse);
+    var step;
+    var iterations = 0;
+    while (!(step = iterator.next()).done) {
+      iterations++;
+      if (fn(step.value[1], step.value[0], this) === false) {
+        break;
+      }
+    }
+    return iterations;
+    */
+    // indexed:
+    var iterator = this.__iterator(ITERATE_VALUES, reverse);
+    var step;
+    var iterations = 0;
+    while (!(step = iterator.next()).done) {
+      if (fn(step.value, iterations++, this) === false) {
+        break;
+      }
+    }
+    return iterations;
+  };
+  zipSequence.__iteratorUncached = function (type, reverse) {
+    var iterators = iters.map(
+      function (i) { return ((i = Collection(i)), getIterator(reverse ? i.reverse() : i)); }
+    );
+    var iterations = 0;
+    var isDone = false;
+    return new Iterator(function () {
+      var steps;
+      if (!isDone) {
+        steps = iterators.map(function (i) { return i.next(); });
+        isDone = zipAll ? steps.every(function (s) { return s.done; }) : steps.some(function (s) { return s.done; });
+      }
+      if (isDone) {
+        return iteratorDone();
+      }
+      return iteratorValue(
+        type,
+        iterations++,
+        zipper.apply(
+          null,
+          steps.map(function (s) { return s.value; })
+        )
+      );
+    });
+  };
+  return zipSequence;
+}
+
+// #pragma Helper Functions
+
+function reify(iter, seq) {
+  return iter === seq ? iter : isSeq(iter) ? seq : iter.constructor(seq);
+}
+
+function validateEntry(entry) {
+  if (entry !== Object(entry)) {
+    throw new TypeError('Expected [K, V] tuple: ' + entry);
+  }
+}
+
+function collectionClass(collection) {
+  return isKeyed(collection)
+    ? KeyedCollection
+    : isIndexed(collection)
+    ? IndexedCollection
+    : SetCollection;
+}
+
+function makeSequence(collection) {
+  return Object.create(
+    (isKeyed(collection)
+      ? KeyedSeq
+      : isIndexed(collection)
+      ? IndexedSeq
+      : SetSeq
+    ).prototype
+  );
+}
+
+function cacheResultThrough() {
+  if (this._iter.cacheResult) {
+    this._iter.cacheResult();
+    this.size = this._iter.size;
+    return this;
+  }
+  return Seq.prototype.cacheResult.call(this);
+}
+
+function defaultComparator(a, b) {
+  if (a === undefined && b === undefined) {
+    return 0;
+  }
+
+  if (a === undefined) {
+    return 1;
+  }
+
+  if (b === undefined) {
+    return -1;
+  }
+
+  return a > b ? 1 : a < b ? -1 : 0;
+}
+
+// http://jsperf.com/copy-array-inline
+function arrCopy(arr, offset) {
+  offset = offset || 0;
+  var len = Math.max(0, arr.length - offset);
+  var newArr = new Array(len);
+  for (var ii = 0; ii < len; ii++) {
+    newArr[ii] = arr[ii + offset];
+  }
+  return newArr;
+}
+
+function invariant(condition, error) {
+  if (!condition) { throw new Error(error); }
+}
+
+function assertNotInfinite(size) {
+  invariant(
+    size !== Infinity,
+    'Cannot perform this action with an infinite size.'
+  );
+}
+
+function coerceKeyPath(keyPath) {
+  if (isArrayLike(keyPath) && typeof keyPath !== 'string') {
+    return keyPath;
+  }
+  if (isOrdered(keyPath)) {
+    return keyPath.toArray();
+  }
+  throw new TypeError(
+    'Invalid keyPath: expected Ordered Collection or Array: ' + keyPath
+  );
+}
+
+var toString = Object.prototype.toString;
+
+function isPlainObject(value) {
+  // The base prototype's toString deals with Argument objects and native namespaces like Math
+  if (
+    !value ||
+    typeof value !== 'object' ||
+    toString.call(value) !== '[object Object]'
+  ) {
+    return false;
+  }
+
+  var proto = Object.getPrototypeOf(value);
+  if (proto === null) {
+    return true;
+  }
+
+  // Iteratively going up the prototype chain is needed for cross-realm environments (differing contexts, iframes, etc)
+  var parentProto = proto;
+  var nextProto = Object.getPrototypeOf(proto);
+  while (nextProto !== null) {
+    parentProto = nextProto;
+    nextProto = Object.getPrototypeOf(parentProto);
+  }
+  return parentProto === proto;
+}
+
+/**
+ * Returns true if the value is a potentially-persistent data structure, either
+ * provided by Immutable.js or a plain Array or Object.
+ */
+function isDataStructure(value) {
+  return (
+    typeof value === 'object' &&
+    (isImmutable(value) || Array.isArray(value) || isPlainObject(value))
+  );
+}
+
+/**
+ * Converts a value to a string, adding quotes if a string was provided.
+ */
+function quoteString(value) {
+  try {
+    return typeof value === 'string' ? JSON.stringify(value) : String(value);
+  } catch (_ignoreError) {
+    return JSON.stringify(value);
+  }
+}
+
+function has(collection, key) {
+  return isImmutable(collection)
+    ? collection.has(key)
+    : isDataStructure(collection) && hasOwnProperty.call(collection, key);
+}
+
+function get(collection, key, notSetValue) {
+  return isImmutable(collection)
+    ? collection.get(key, notSetValue)
+    : !has(collection, key)
+    ? notSetValue
+    : typeof collection.get === 'function'
+    ? collection.get(key)
+    : collection[key];
+}
+
+function shallowCopy(from) {
+  if (Array.isArray(from)) {
+    return arrCopy(from);
+  }
+  var to = {};
+  for (var key in from) {
+    if (hasOwnProperty.call(from, key)) {
+      to[key] = from[key];
+    }
+  }
+  return to;
+}
+
+function remove(collection, key) {
+  if (!isDataStructure(collection)) {
+    throw new TypeError(
+      'Cannot update non-data-structure value: ' + collection
+    );
+  }
+  if (isImmutable(collection)) {
+    if (!collection.remove) {
+      throw new TypeError(
+        'Cannot update immutable value without .remove() method: ' + collection
+      );
+    }
+    return collection.remove(key);
+  }
+  if (!hasOwnProperty.call(collection, key)) {
+    return collection;
+  }
+  var collectionCopy = shallowCopy(collection);
+  if (Array.isArray(collectionCopy)) {
+    collectionCopy.splice(key, 1);
+  } else {
+    delete collectionCopy[key];
+  }
+  return collectionCopy;
+}
+
+function set(collection, key, value) {
+  if (!isDataStructure(collection)) {
+    throw new TypeError(
+      'Cannot update non-data-structure value: ' + collection
+    );
+  }
+  if (isImmutable(collection)) {
+    if (!collection.set) {
+      throw new TypeError(
+        'Cannot update immutable value without .set() method: ' + collection
+      );
+    }
+    return collection.set(key, value);
+  }
+  if (hasOwnProperty.call(collection, key) && value === collection[key]) {
+    return collection;
+  }
+  var collectionCopy = shallowCopy(collection);
+  collectionCopy[key] = value;
+  return collectionCopy;
+}
+
+function updateIn$1(collection, keyPath, notSetValue, updater) {
+  if (!updater) {
+    updater = notSetValue;
+    notSetValue = undefined;
+  }
+  var updatedValue = updateInDeeply(
+    isImmutable(collection),
+    collection,
+    coerceKeyPath(keyPath),
+    0,
+    notSetValue,
+    updater
+  );
+  return updatedValue === NOT_SET ? notSetValue : updatedValue;
+}
+
+function updateInDeeply(
+  inImmutable,
+  existing,
+  keyPath,
+  i,
+  notSetValue,
+  updater
+) {
+  var wasNotSet = existing === NOT_SET;
+  if (i === keyPath.length) {
+    var existingValue = wasNotSet ? notSetValue : existing;
+    var newValue = updater(existingValue);
+    return newValue === existingValue ? existing : newValue;
+  }
+  if (!wasNotSet && !isDataStructure(existing)) {
+    throw new TypeError(
+      'Cannot update within non-data-structure value in path [' +
+        keyPath.slice(0, i).map(quoteString) +
+        ']: ' +
+        existing
+    );
+  }
+  var key = keyPath[i];
+  var nextExisting = wasNotSet ? NOT_SET : get(existing, key, NOT_SET);
+  var nextUpdated = updateInDeeply(
+    nextExisting === NOT_SET ? inImmutable : isImmutable(nextExisting),
+    nextExisting,
+    keyPath,
+    i + 1,
+    notSetValue,
+    updater
+  );
+  return nextUpdated === nextExisting
+    ? existing
+    : nextUpdated === NOT_SET
+    ? remove(existing, key)
+    : set(
+        wasNotSet ? (inImmutable ? emptyMap() : {}) : existing,
+        key,
+        nextUpdated
+      );
+}
+
+function setIn$1(collection, keyPath, value) {
+  return updateIn$1(collection, keyPath, NOT_SET, function () { return value; });
+}
+
+function setIn(keyPath, v) {
+  return setIn$1(this, keyPath, v);
+}
+
+function removeIn(collection, keyPath) {
+  return updateIn$1(collection, keyPath, function () { return NOT_SET; });
+}
+
+function deleteIn(keyPath) {
+  return removeIn(this, keyPath);
+}
+
+function update$1(collection, key, notSetValue, updater) {
+  return updateIn$1(collection, [key], notSetValue, updater);
+}
+
+function update(key, notSetValue, updater) {
+  return arguments.length === 1
+    ? key(this)
+    : update$1(this, key, notSetValue, updater);
+}
+
+function updateIn(keyPath, notSetValue, updater) {
+  return updateIn$1(this, keyPath, notSetValue, updater);
+}
+
+function merge$1() {
+  var iters = [], len = arguments.length;
+  while ( len-- ) iters[ len ] = arguments[ len ];
+
+  return mergeIntoKeyedWith(this, iters);
+}
+
+function mergeWith$1(merger) {
+  var iters = [], len = arguments.length - 1;
+  while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+  if (typeof merger !== 'function') {
+    throw new TypeError('Invalid merger function: ' + merger);
+  }
+  return mergeIntoKeyedWith(this, iters, merger);
+}
+
+function mergeIntoKeyedWith(collection, collections, merger) {
+  var iters = [];
+  for (var ii = 0; ii < collections.length; ii++) {
+    var collection$1 = KeyedCollection(collections[ii]);
+    if (collection$1.size !== 0) {
+      iters.push(collection$1);
+    }
+  }
+  if (iters.length === 0) {
+    return collection;
+  }
+  if (
+    collection.toSeq().size === 0 &&
+    !collection.__ownerID &&
+    iters.length === 1
+  ) {
+    return collection.constructor(iters[0]);
+  }
+  return collection.withMutations(function (collection) {
+    var mergeIntoCollection = merger
+      ? function (value, key) {
+          update$1(collection, key, NOT_SET, function (oldVal) { return oldVal === NOT_SET ? value : merger(oldVal, value, key); }
+          );
+        }
+      : function (value, key) {
+          collection.set(key, value);
+        };
+    for (var ii = 0; ii < iters.length; ii++) {
+      iters[ii].forEach(mergeIntoCollection);
+    }
+  });
+}
+
+function merge(collection) {
+  var sources = [], len = arguments.length - 1;
+  while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];
+
+  return mergeWithSources(collection, sources);
+}
+
+function mergeWith(merger, collection) {
+  var sources = [], len = arguments.length - 2;
+  while ( len-- > 0 ) sources[ len ] = arguments[ len + 2 ];
+
+  return mergeWithSources(collection, sources, merger);
+}
+
+function mergeDeep$1(collection) {
+  var sources = [], len = arguments.length - 1;
+  while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];
+
+  return mergeDeepWithSources(collection, sources);
+}
+
+function mergeDeepWith$1(merger, collection) {
+  var sources = [], len = arguments.length - 2;
+  while ( len-- > 0 ) sources[ len ] = arguments[ len + 2 ];
+
+  return mergeDeepWithSources(collection, sources, merger);
+}
+
+function mergeDeepWithSources(collection, sources, merger) {
+  return mergeWithSources(collection, sources, deepMergerWith(merger));
+}
+
+function mergeWithSources(collection, sources, merger) {
+  if (!isDataStructure(collection)) {
+    throw new TypeError(
+      'Cannot merge into non-data-structure value: ' + collection
+    );
+  }
+  if (isImmutable(collection)) {
+    return typeof merger === 'function' && collection.mergeWith
+      ? collection.mergeWith.apply(collection, [ merger ].concat( sources ))
+      : collection.merge
+      ? collection.merge.apply(collection, sources)
+      : collection.concat.apply(collection, sources);
+  }
+  var isArray = Array.isArray(collection);
+  var merged = collection;
+  var Collection = isArray ? IndexedCollection : KeyedCollection;
+  var mergeItem = isArray
+    ? function (value) {
+        // Copy on write
+        if (merged === collection) {
+          merged = shallowCopy(merged);
+        }
+        merged.push(value);
+      }
+    : function (value, key) {
+        var hasVal = hasOwnProperty.call(merged, key);
+        var nextVal =
+          hasVal && merger ? merger(merged[key], value, key) : value;
+        if (!hasVal || nextVal !== merged[key]) {
+          // Copy on write
+          if (merged === collection) {
+            merged = shallowCopy(merged);
+          }
+          merged[key] = nextVal;
+        }
+      };
+  for (var i = 0; i < sources.length; i++) {
+    Collection(sources[i]).forEach(mergeItem);
+  }
+  return merged;
+}
+
+function deepMergerWith(merger) {
+  function deepMerger(oldValue, newValue, key) {
+    return isDataStructure(oldValue) &&
+      isDataStructure(newValue) &&
+      areMergeable(oldValue, newValue)
+      ? mergeWithSources(oldValue, [newValue], deepMerger)
+      : merger
+      ? merger(oldValue, newValue, key)
+      : newValue;
+  }
+  return deepMerger;
+}
+
+/**
+ * It's unclear what the desired behavior is for merging two collections that
+ * fall into separate categories between keyed, indexed, or set-like, so we only
+ * consider them mergeable if they fall into the same category.
+ */
+function areMergeable(oldDataStructure, newDataStructure) {
+  var oldSeq = Seq(oldDataStructure);
+  var newSeq = Seq(newDataStructure);
+  // This logic assumes that a sequence can only fall into one of the three
+  // categories mentioned above (since there's no `isSetLike()` method).
+  return (
+    isIndexed(oldSeq) === isIndexed(newSeq) &&
+    isKeyed(oldSeq) === isKeyed(newSeq)
+  );
+}
+
+function mergeDeep() {
+  var iters = [], len = arguments.length;
+  while ( len-- ) iters[ len ] = arguments[ len ];
+
+  return mergeDeepWithSources(this, iters);
+}
+
+function mergeDeepWith(merger) {
+  var iters = [], len = arguments.length - 1;
+  while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+  return mergeDeepWithSources(this, iters, merger);
+}
+
+function mergeIn(keyPath) {
+  var iters = [], len = arguments.length - 1;
+  while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+  return updateIn$1(this, keyPath, emptyMap(), function (m) { return mergeWithSources(m, iters); });
+}
+
+function mergeDeepIn(keyPath) {
+  var iters = [], len = arguments.length - 1;
+  while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+  return updateIn$1(this, keyPath, emptyMap(), function (m) { return mergeDeepWithSources(m, iters); }
+  );
+}
+
+function withMutations(fn) {
+  var mutable = this.asMutable();
+  fn(mutable);
+  return mutable.wasAltered() ? mutable.__ensureOwner(this.__ownerID) : this;
+}
+
+function asMutable() {
+  return this.__ownerID ? this : this.__ensureOwner(new OwnerID());
+}
+
+function asImmutable() {
+  return this.__ensureOwner();
+}
+
+function wasAltered() {
+  return this.__altered;
+}
+
+var Map = /*@__PURE__*/(function (KeyedCollection) {
+  function Map(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptyMap()
+      : isMap(value) && !isOrdered(value)
+      ? value
+      : emptyMap().withMutations(function (map) {
+          var iter = KeyedCollection(value);
+          assertNotInfinite(iter.size);
+          iter.forEach(function (v, k) { return map.set(k, v); });
+        });
+  }
+
+  if ( KeyedCollection ) Map.__proto__ = KeyedCollection;
+  Map.prototype = Object.create( KeyedCollection && KeyedCollection.prototype );
+  Map.prototype.constructor = Map;
+
+  Map.prototype.toString = function toString () {
+    return this.__toString('Map {', '}');
+  };
+
+  // @pragma Access
+
+  Map.prototype.get = function get (k, notSetValue) {
+    return this._root
+      ? this._root.get(0, undefined, k, notSetValue)
+      : notSetValue;
+  };
+
+  // @pragma Modification
+
+  Map.prototype.set = function set (k, v) {
+    return updateMap(this, k, v);
+  };
+
+  Map.prototype.remove = function remove (k) {
+    return updateMap(this, k, NOT_SET);
+  };
+
+  Map.prototype.deleteAll = function deleteAll (keys) {
+    var collection = Collection(keys);
+
+    if (collection.size === 0) {
+      return this;
+    }
+
+    return this.withMutations(function (map) {
+      collection.forEach(function (key) { return map.remove(key); });
+    });
+  };
+
+  Map.prototype.clear = function clear () {
+    if (this.size === 0) {
+      return this;
+    }
+    if (this.__ownerID) {
+      this.size = 0;
+      this._root = null;
+      this.__hash = undefined;
+      this.__altered = true;
+      return this;
+    }
+    return emptyMap();
+  };
+
+  // @pragma Composition
+
+  Map.prototype.sort = function sort (comparator) {
+    // Late binding
+    return OrderedMap(sortFactory(this, comparator));
+  };
+
+  Map.prototype.sortBy = function sortBy (mapper, comparator) {
+    // Late binding
+    return OrderedMap(sortFactory(this, comparator, mapper));
+  };
+
+  Map.prototype.map = function map (mapper, context) {
+    var this$1$1 = this;
+
+    return this.withMutations(function (map) {
+      map.forEach(function (value, key) {
+        map.set(key, mapper.call(context, value, key, this$1$1));
+      });
+    });
+  };
+
+  // @pragma Mutability
+
+  Map.prototype.__iterator = function __iterator (type, reverse) {
+    return new MapIterator(this, type, reverse);
+  };
+
+  Map.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    var iterations = 0;
+    this._root &&
+      this._root.iterate(function (entry) {
+        iterations++;
+        return fn(entry[1], entry[0], this$1$1);
+      }, reverse);
+    return iterations;
+  };
+
+  Map.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+    if (ownerID === this.__ownerID) {
+      return this;
+    }
+    if (!ownerID) {
+      if (this.size === 0) {
+        return emptyMap();
+      }
+      this.__ownerID = ownerID;
+      this.__altered = false;
+      return this;
+    }
+    return makeMap(this.size, this._root, ownerID, this.__hash);
+  };
+
+  return Map;
+}(KeyedCollection));
+
+Map.isMap = isMap;
+
+var MapPrototype = Map.prototype;
+MapPrototype[IS_MAP_SYMBOL] = true;
+MapPrototype[DELETE] = MapPrototype.remove;
+MapPrototype.removeAll = MapPrototype.deleteAll;
+MapPrototype.setIn = setIn;
+MapPrototype.removeIn = MapPrototype.deleteIn = deleteIn;
+MapPrototype.update = update;
+MapPrototype.updateIn = updateIn;
+MapPrototype.merge = MapPrototype.concat = merge$1;
+MapPrototype.mergeWith = mergeWith$1;
+MapPrototype.mergeDeep = mergeDeep;
+MapPrototype.mergeDeepWith = mergeDeepWith;
+MapPrototype.mergeIn = mergeIn;
+MapPrototype.mergeDeepIn = mergeDeepIn;
+MapPrototype.withMutations = withMutations;
+MapPrototype.wasAltered = wasAltered;
+MapPrototype.asImmutable = asImmutable;
+MapPrototype['@@transducer/init'] = MapPrototype.asMutable = asMutable;
+MapPrototype['@@transducer/step'] = function (result, arr) {
+  return result.set(arr[0], arr[1]);
+};
+MapPrototype['@@transducer/result'] = function (obj) {
+  return obj.asImmutable();
+};
+
+// #pragma Trie Nodes
+
+var ArrayMapNode = function ArrayMapNode(ownerID, entries) {
+  this.ownerID = ownerID;
+  this.entries = entries;
+};
+
+ArrayMapNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+  var entries = this.entries;
+  for (var ii = 0, len = entries.length; ii < len; ii++) {
+    if (is(key, entries[ii][0])) {
+      return entries[ii][1];
+    }
+  }
+  return notSetValue;
+};
+
+ArrayMapNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+  var removed = value === NOT_SET;
+
+  var entries = this.entries;
+  var idx = 0;
+  var len = entries.length;
+  for (; idx < len; idx++) {
+    if (is(key, entries[idx][0])) {
+      break;
+    }
+  }
+  var exists = idx < len;
+
+  if (exists ? entries[idx][1] === value : removed) {
+    return this;
+  }
+
+  SetRef(didAlter);
+  (removed || !exists) && SetRef(didChangeSize);
+
+  if (removed && entries.length === 1) {
+    return; // undefined
+  }
+
+  if (!exists && !removed && entries.length >= MAX_ARRAY_MAP_SIZE) {
+    return createNodes(ownerID, entries, key, value);
+  }
+
+  var isEditable = ownerID && ownerID === this.ownerID;
+  var newEntries = isEditable ? entries : arrCopy(entries);
+
+  if (exists) {
+    if (removed) {
+      idx === len - 1
+        ? newEntries.pop()
+        : (newEntries[idx] = newEntries.pop());
+    } else {
+      newEntries[idx] = [key, value];
+    }
+  } else {
+    newEntries.push([key, value]);
+  }
+
+  if (isEditable) {
+    this.entries = newEntries;
+    return this;
+  }
+
+  return new ArrayMapNode(ownerID, newEntries);
+};
+
+var BitmapIndexedNode = function BitmapIndexedNode(ownerID, bitmap, nodes) {
+  this.ownerID = ownerID;
+  this.bitmap = bitmap;
+  this.nodes = nodes;
+};
+
+BitmapIndexedNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+  if (keyHash === undefined) {
+    keyHash = hash(key);
+  }
+  var bit = 1 << ((shift === 0 ? keyHash : keyHash >>> shift) & MASK);
+  var bitmap = this.bitmap;
+  return (bitmap & bit) === 0
+    ? notSetValue
+    : this.nodes[popCount(bitmap & (bit - 1))].get(
+        shift + SHIFT,
+        keyHash,
+        key,
+        notSetValue
+      );
+};
+
+BitmapIndexedNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+  if (keyHash === undefined) {
+    keyHash = hash(key);
+  }
+  var keyHashFrag = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+  var bit = 1 << keyHashFrag;
+  var bitmap = this.bitmap;
+  var exists = (bitmap & bit) !== 0;
+
+  if (!exists && value === NOT_SET) {
+    return this;
+  }
+
+  var idx = popCount(bitmap & (bit - 1));
+  var nodes = this.nodes;
+  var node = exists ? nodes[idx] : undefined;
+  var newNode = updateNode(
+    node,
+    ownerID,
+    shift + SHIFT,
+    keyHash,
+    key,
+    value,
+    didChangeSize,
+    didAlter
+  );
+
+  if (newNode === node) {
+    return this;
+  }
+
+  if (!exists && newNode && nodes.length >= MAX_BITMAP_INDEXED_SIZE) {
+    return expandNodes(ownerID, nodes, bitmap, keyHashFrag, newNode);
+  }
+
+  if (
+    exists &&
+    !newNode &&
+    nodes.length === 2 &&
+    isLeafNode(nodes[idx ^ 1])
+  ) {
+    return nodes[idx ^ 1];
+  }
+
+  if (exists && newNode && nodes.length === 1 && isLeafNode(newNode)) {
+    return newNode;
+  }
+
+  var isEditable = ownerID && ownerID === this.ownerID;
+  var newBitmap = exists ? (newNode ? bitmap : bitmap ^ bit) : bitmap | bit;
+  var newNodes = exists
+    ? newNode
+      ? setAt(nodes, idx, newNode, isEditable)
+      : spliceOut(nodes, idx, isEditable)
+    : spliceIn(nodes, idx, newNode, isEditable);
+
+  if (isEditable) {
+    this.bitmap = newBitmap;
+    this.nodes = newNodes;
+    return this;
+  }
+
+  return new BitmapIndexedNode(ownerID, newBitmap, newNodes);
+};
+
+var HashArrayMapNode = function HashArrayMapNode(ownerID, count, nodes) {
+  this.ownerID = ownerID;
+  this.count = count;
+  this.nodes = nodes;
+};
+
+HashArrayMapNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+  if (keyHash === undefined) {
+    keyHash = hash(key);
+  }
+  var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+  var node = this.nodes[idx];
+  return node
+    ? node.get(shift + SHIFT, keyHash, key, notSetValue)
+    : notSetValue;
+};
+
+HashArrayMapNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+  if (keyHash === undefined) {
+    keyHash = hash(key);
+  }
+  var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+  var removed = value === NOT_SET;
+  var nodes = this.nodes;
+  var node = nodes[idx];
+
+  if (removed && !node) {
+    return this;
+  }
+
+  var newNode = updateNode(
+    node,
+    ownerID,
+    shift + SHIFT,
+    keyHash,
+    key,
+    value,
+    didChangeSize,
+    didAlter
+  );
+  if (newNode === node) {
+    return this;
+  }
+
+  var newCount = this.count;
+  if (!node) {
+    newCount++;
+  } else if (!newNode) {
+    newCount--;
+    if (newCount < MIN_HASH_ARRAY_MAP_SIZE) {
+      return packNodes(ownerID, nodes, newCount, idx);
+    }
+  }
+
+  var isEditable = ownerID && ownerID === this.ownerID;
+  var newNodes = setAt(nodes, idx, newNode, isEditable);
+
+  if (isEditable) {
+    this.count = newCount;
+    this.nodes = newNodes;
+    return this;
+  }
+
+  return new HashArrayMapNode(ownerID, newCount, newNodes);
+};
+
+var HashCollisionNode = function HashCollisionNode(ownerID, keyHash, entries) {
+  this.ownerID = ownerID;
+  this.keyHash = keyHash;
+  this.entries = entries;
+};
+
+HashCollisionNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+  var entries = this.entries;
+  for (var ii = 0, len = entries.length; ii < len; ii++) {
+    if (is(key, entries[ii][0])) {
+      return entries[ii][1];
+    }
+  }
+  return notSetValue;
+};
+
+HashCollisionNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+  if (keyHash === undefined) {
+    keyHash = hash(key);
+  }
+
+  var removed = value === NOT_SET;
+
+  if (keyHash !== this.keyHash) {
+    if (removed) {
+      return this;
+    }
+    SetRef(didAlter);
+    SetRef(didChangeSize);
+    return mergeIntoNode(this, ownerID, shift, keyHash, [key, value]);
+  }
+
+  var entries = this.entries;
+  var idx = 0;
+  var len = entries.length;
+  for (; idx < len; idx++) {
+    if (is(key, entries[idx][0])) {
+      break;
+    }
+  }
+  var exists = idx < len;
+
+  if (exists ? entries[idx][1] === value : removed) {
+    return this;
+  }
+
+  SetRef(didAlter);
+  (removed || !exists) && SetRef(didChangeSize);
+
+  if (removed && len === 2) {
+    return new ValueNode(ownerID, this.keyHash, entries[idx ^ 1]);
+  }
+
+  var isEditable = ownerID && ownerID === this.ownerID;
+  var newEntries = isEditable ? entries : arrCopy(entries);
+
+  if (exists) {
+    if (removed) {
+      idx === len - 1
+        ? newEntries.pop()
+        : (newEntries[idx] = newEntries.pop());
+    } else {
+      newEntries[idx] = [key, value];
+    }
+  } else {
+    newEntries.push([key, value]);
+  }
+
+  if (isEditable) {
+    this.entries = newEntries;
+    return this;
+  }
+
+  return new HashCollisionNode(ownerID, this.keyHash, newEntries);
+};
+
+var ValueNode = function ValueNode(ownerID, keyHash, entry) {
+  this.ownerID = ownerID;
+  this.keyHash = keyHash;
+  this.entry = entry;
+};
+
+ValueNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+  return is(key, this.entry[0]) ? this.entry[1] : notSetValue;
+};
+
+ValueNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+  var removed = value === NOT_SET;
+  var keyMatch = is(key, this.entry[0]);
+  if (keyMatch ? value === this.entry[1] : removed) {
+    return this;
+  }
+
+  SetRef(didAlter);
+
+  if (removed) {
+    SetRef(didChangeSize);
+    return; // undefined
+  }
+
+  if (keyMatch) {
+    if (ownerID && ownerID === this.ownerID) {
+      this.entry[1] = value;
+      return this;
+    }
+    return new ValueNode(ownerID, this.keyHash, [key, value]);
+  }
+
+  SetRef(didChangeSize);
+  return mergeIntoNode(this, ownerID, shift, hash(key), [key, value]);
+};
+
+// #pragma Iterators
+
+ArrayMapNode.prototype.iterate = HashCollisionNode.prototype.iterate =
+  function (fn, reverse) {
+    var entries = this.entries;
+    for (var ii = 0, maxIndex = entries.length - 1; ii <= maxIndex; ii++) {
+      if (fn(entries[reverse ? maxIndex - ii : ii]) === false) {
+        return false;
+      }
+    }
+  };
+
+BitmapIndexedNode.prototype.iterate = HashArrayMapNode.prototype.iterate =
+  function (fn, reverse) {
+    var nodes = this.nodes;
+    for (var ii = 0, maxIndex = nodes.length - 1; ii <= maxIndex; ii++) {
+      var node = nodes[reverse ? maxIndex - ii : ii];
+      if (node && node.iterate(fn, reverse) === false) {
+        return false;
+      }
+    }
+  };
+
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+ValueNode.prototype.iterate = function (fn, reverse) {
+  return fn(this.entry);
+};
+
+var MapIterator = /*@__PURE__*/(function (Iterator) {
+  function MapIterator(map, type, reverse) {
+    this._type = type;
+    this._reverse = reverse;
+    this._stack = map._root && mapIteratorFrame(map._root);
+  }
+
+  if ( Iterator ) MapIterator.__proto__ = Iterator;
+  MapIterator.prototype = Object.create( Iterator && Iterator.prototype );
+  MapIterator.prototype.constructor = MapIterator;
+
+  MapIterator.prototype.next = function next () {
+    var type = this._type;
+    var stack = this._stack;
+    while (stack) {
+      var node = stack.node;
+      var index = stack.index++;
+      var maxIndex = (void 0);
+      if (node.entry) {
+        if (index === 0) {
+          return mapIteratorValue(type, node.entry);
+        }
+      } else if (node.entries) {
+        maxIndex = node.entries.length - 1;
+        if (index <= maxIndex) {
+          return mapIteratorValue(
+            type,
+            node.entries[this._reverse ? maxIndex - index : index]
+          );
+        }
+      } else {
+        maxIndex = node.nodes.length - 1;
+        if (index <= maxIndex) {
+          var subNode = node.nodes[this._reverse ? maxIndex - index : index];
+          if (subNode) {
+            if (subNode.entry) {
+              return mapIteratorValue(type, subNode.entry);
+            }
+            stack = this._stack = mapIteratorFrame(subNode, stack);
+          }
+          continue;
+        }
+      }
+      stack = this._stack = this._stack.__prev;
+    }
+    return iteratorDone();
+  };
+
+  return MapIterator;
+}(Iterator));
+
+function mapIteratorValue(type, entry) {
+  return iteratorValue(type, entry[0], entry[1]);
+}
+
+function mapIteratorFrame(node, prev) {
+  return {
+    node: node,
+    index: 0,
+    __prev: prev,
+  };
+}
+
+function makeMap(size, root, ownerID, hash) {
+  var map = Object.create(MapPrototype);
+  map.size = size;
+  map._root = root;
+  map.__ownerID = ownerID;
+  map.__hash = hash;
+  map.__altered = false;
+  return map;
+}
+
+var EMPTY_MAP;
+function emptyMap() {
+  return EMPTY_MAP || (EMPTY_MAP = makeMap(0));
+}
+
+function updateMap(map, k, v) {
+  var newRoot;
+  var newSize;
+  if (!map._root) {
+    if (v === NOT_SET) {
+      return map;
+    }
+    newSize = 1;
+    newRoot = new ArrayMapNode(map.__ownerID, [[k, v]]);
+  } else {
+    var didChangeSize = MakeRef();
+    var didAlter = MakeRef();
+    newRoot = updateNode(
+      map._root,
+      map.__ownerID,
+      0,
+      undefined,
+      k,
+      v,
+      didChangeSize,
+      didAlter
+    );
+    if (!didAlter.value) {
+      return map;
+    }
+    newSize = map.size + (didChangeSize.value ? (v === NOT_SET ? -1 : 1) : 0);
+  }
+  if (map.__ownerID) {
+    map.size = newSize;
+    map._root = newRoot;
+    map.__hash = undefined;
+    map.__altered = true;
+    return map;
+  }
+  return newRoot ? makeMap(newSize, newRoot) : emptyMap();
+}
+
+function updateNode(
+  node,
+  ownerID,
+  shift,
+  keyHash,
+  key,
+  value,
+  didChangeSize,
+  didAlter
+) {
+  if (!node) {
+    if (value === NOT_SET) {
+      return node;
+    }
+    SetRef(didAlter);
+    SetRef(didChangeSize);
+    return new ValueNode(ownerID, keyHash, [key, value]);
+  }
+  return node.update(
+    ownerID,
+    shift,
+    keyHash,
+    key,
+    value,
+    didChangeSize,
+    didAlter
+  );
+}
+
+function isLeafNode(node) {
+  return (
+    node.constructor === ValueNode || node.constructor === HashCollisionNode
+  );
+}
+
+function mergeIntoNode(node, ownerID, shift, keyHash, entry) {
+  if (node.keyHash === keyHash) {
+    return new HashCollisionNode(ownerID, keyHash, [node.entry, entry]);
+  }
+
+  var idx1 = (shift === 0 ? node.keyHash : node.keyHash >>> shift) & MASK;
+  var idx2 = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+
+  var newNode;
+  var nodes =
+    idx1 === idx2
+      ? [mergeIntoNode(node, ownerID, shift + SHIFT, keyHash, entry)]
+      : ((newNode = new ValueNode(ownerID, keyHash, entry)),
+        idx1 < idx2 ? [node, newNode] : [newNode, node]);
+
+  return new BitmapIndexedNode(ownerID, (1 << idx1) | (1 << idx2), nodes);
+}
+
+function createNodes(ownerID, entries, key, value) {
+  if (!ownerID) {
+    ownerID = new OwnerID();
+  }
+  var node = new ValueNode(ownerID, hash(key), [key, value]);
+  for (var ii = 0; ii < entries.length; ii++) {
+    var entry = entries[ii];
+    node = node.update(ownerID, 0, undefined, entry[0], entry[1]);
+  }
+  return node;
+}
+
+function packNodes(ownerID, nodes, count, excluding) {
+  var bitmap = 0;
+  var packedII = 0;
+  var packedNodes = new Array(count);
+  for (var ii = 0, bit = 1, len = nodes.length; ii < len; ii++, bit <<= 1) {
+    var node = nodes[ii];
+    if (node !== undefined && ii !== excluding) {
+      bitmap |= bit;
+      packedNodes[packedII++] = node;
+    }
+  }
+  return new BitmapIndexedNode(ownerID, bitmap, packedNodes);
+}
+
+function expandNodes(ownerID, nodes, bitmap, including, node) {
+  var count = 0;
+  var expandedNodes = new Array(SIZE);
+  for (var ii = 0; bitmap !== 0; ii++, bitmap >>>= 1) {
+    expandedNodes[ii] = bitmap & 1 ? nodes[count++] : undefined;
+  }
+  expandedNodes[including] = node;
+  return new HashArrayMapNode(ownerID, count + 1, expandedNodes);
+}
+
+function popCount(x) {
+  x -= (x >> 1) & 0x55555555;
+  x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+  x = (x + (x >> 4)) & 0x0f0f0f0f;
+  x += x >> 8;
+  x += x >> 16;
+  return x & 0x7f;
+}
+
+function setAt(array, idx, val, canEdit) {
+  var newArray = canEdit ? array : arrCopy(array);
+  newArray[idx] = val;
+  return newArray;
+}
+
+function spliceIn(array, idx, val, canEdit) {
+  var newLen = array.length + 1;
+  if (canEdit && idx + 1 === newLen) {
+    array[idx] = val;
+    return array;
+  }
+  var newArray = new Array(newLen);
+  var after = 0;
+  for (var ii = 0; ii < newLen; ii++) {
+    if (ii === idx) {
+      newArray[ii] = val;
+      after = -1;
+    } else {
+      newArray[ii] = array[ii + after];
+    }
+  }
+  return newArray;
+}
+
+function spliceOut(array, idx, canEdit) {
+  var newLen = array.length - 1;
+  if (canEdit && idx === newLen) {
+    array.pop();
+    return array;
+  }
+  var newArray = new Array(newLen);
+  var after = 0;
+  for (var ii = 0; ii < newLen; ii++) {
+    if (ii === idx) {
+      after = 1;
+    }
+    newArray[ii] = array[ii + after];
+  }
+  return newArray;
+}
+
+var MAX_ARRAY_MAP_SIZE = SIZE / 4;
+var MAX_BITMAP_INDEXED_SIZE = SIZE / 2;
+var MIN_HASH_ARRAY_MAP_SIZE = SIZE / 4;
+
+var IS_LIST_SYMBOL = '@@__IMMUTABLE_LIST__@@';
+
+function isList(maybeList) {
+  return Boolean(maybeList && maybeList[IS_LIST_SYMBOL]);
+}
+
+var List = /*@__PURE__*/(function (IndexedCollection) {
+  function List(value) {
+    var empty = emptyList();
+    if (value === undefined || value === null) {
+      // eslint-disable-next-line no-constructor-return
+      return empty;
+    }
+    if (isList(value)) {
+      // eslint-disable-next-line no-constructor-return
+      return value;
+    }
+    var iter = IndexedCollection(value);
+    var size = iter.size;
+    if (size === 0) {
+      // eslint-disable-next-line no-constructor-return
+      return empty;
+    }
+    assertNotInfinite(size);
+    if (size > 0 && size < SIZE) {
+      // eslint-disable-next-line no-constructor-return
+      return makeList(0, size, SHIFT, null, new VNode(iter.toArray()));
+    }
+    // eslint-disable-next-line no-constructor-return
+    return empty.withMutations(function (list) {
+      list.setSize(size);
+      iter.forEach(function (v, i) { return list.set(i, v); });
+    });
+  }
+
+  if ( IndexedCollection ) List.__proto__ = IndexedCollection;
+  List.prototype = Object.create( IndexedCollection && IndexedCollection.prototype );
+  List.prototype.constructor = List;
+
+  List.of = function of (/*...values*/) {
+    return this(arguments);
+  };
+
+  List.prototype.toString = function toString () {
+    return this.__toString('List [', ']');
+  };
+
+  // @pragma Access
+
+  List.prototype.get = function get (index, notSetValue) {
+    index = wrapIndex(this, index);
+    if (index >= 0 && index < this.size) {
+      index += this._origin;
+      var node = listNodeFor(this, index);
+      return node && node.array[index & MASK];
+    }
+    return notSetValue;
+  };
+
+  // @pragma Modification
+
+  List.prototype.set = function set (index, value) {
+    return updateList(this, index, value);
+  };
+
+  List.prototype.remove = function remove (index) {
+    return !this.has(index)
+      ? this
+      : index === 0
+      ? this.shift()
+      : index === this.size - 1
+      ? this.pop()
+      : this.splice(index, 1);
+  };
+
+  List.prototype.insert = function insert (index, value) {
+    return this.splice(index, 0, value);
+  };
+
+  List.prototype.clear = function clear () {
+    if (this.size === 0) {
+      return this;
+    }
+    if (this.__ownerID) {
+      this.size = this._origin = this._capacity = 0;
+      this._level = SHIFT;
+      this._root = this._tail = this.__hash = undefined;
+      this.__altered = true;
+      return this;
+    }
+    return emptyList();
+  };
+
+  List.prototype.push = function push (/*...values*/) {
+    var values = arguments;
+    var oldSize = this.size;
+    return this.withMutations(function (list) {
+      setListBounds(list, 0, oldSize + values.length);
+      for (var ii = 0; ii < values.length; ii++) {
+        list.set(oldSize + ii, values[ii]);
+      }
+    });
+  };
+
+  List.prototype.pop = function pop () {
+    return setListBounds(this, 0, -1);
+  };
+
+  List.prototype.unshift = function unshift (/*...values*/) {
+    var values = arguments;
+    return this.withMutations(function (list) {
+      setListBounds(list, -values.length);
+      for (var ii = 0; ii < values.length; ii++) {
+        list.set(ii, values[ii]);
+      }
+    });
+  };
+
+  List.prototype.shift = function shift () {
+    return setListBounds(this, 1);
+  };
+
+  // @pragma Composition
+
+  List.prototype.concat = function concat (/*...collections*/) {
+    var arguments$1 = arguments;
+
+    var seqs = [];
+    for (var i = 0; i < arguments.length; i++) {
+      var argument = arguments$1[i];
+      var seq = IndexedCollection(
+        typeof argument !== 'string' && hasIterator(argument)
+          ? argument
+          : [argument]
+      );
+      if (seq.size !== 0) {
+        seqs.push(seq);
+      }
+    }
+    if (seqs.length === 0) {
+      return this;
+    }
+    if (this.size === 0 && !this.__ownerID && seqs.length === 1) {
+      return this.constructor(seqs[0]);
+    }
+    return this.withMutations(function (list) {
+      seqs.forEach(function (seq) { return seq.forEach(function (value) { return list.push(value); }); });
+    });
+  };
+
+  List.prototype.setSize = function setSize (size) {
+    return setListBounds(this, 0, size);
+  };
+
+  List.prototype.map = function map (mapper, context) {
+    var this$1$1 = this;
+
+    return this.withMutations(function (list) {
+      for (var i = 0; i < this$1$1.size; i++) {
+        list.set(i, mapper.call(context, list.get(i), i, this$1$1));
+      }
+    });
+  };
+
+  // @pragma Iteration
+
+  List.prototype.slice = function slice (begin, end) {
+    var size = this.size;
+    if (wholeSlice(begin, end, size)) {
+      return this;
+    }
+    return setListBounds(
+      this,
+      resolveBegin(begin, size),
+      resolveEnd(end, size)
+    );
+  };
+
+  List.prototype.__iterator = function __iterator (type, reverse) {
+    var index = reverse ? this.size : 0;
+    var values = iterateList(this, reverse);
+    return new Iterator(function () {
+      var value = values();
+      return value === DONE
+        ? iteratorDone()
+        : iteratorValue(type, reverse ? --index : index++, value);
+    });
+  };
+
+  List.prototype.__iterate = function __iterate (fn, reverse) {
+    var index = reverse ? this.size : 0;
+    var values = iterateList(this, reverse);
+    var value;
+    while ((value = values()) !== DONE) {
+      if (fn(value, reverse ? --index : index++, this) === false) {
+        break;
+      }
+    }
+    return index;
+  };
+
+  List.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+    if (ownerID === this.__ownerID) {
+      return this;
+    }
+    if (!ownerID) {
+      if (this.size === 0) {
+        return emptyList();
+      }
+      this.__ownerID = ownerID;
+      this.__altered = false;
+      return this;
+    }
+    return makeList(
+      this._origin,
+      this._capacity,
+      this._level,
+      this._root,
+      this._tail,
+      ownerID,
+      this.__hash
+    );
+  };
+
+  return List;
+}(IndexedCollection));
+
+List.isList = isList;
+
+var ListPrototype = List.prototype;
+ListPrototype[IS_LIST_SYMBOL] = true;
+ListPrototype[DELETE] = ListPrototype.remove;
+ListPrototype.merge = ListPrototype.concat;
+ListPrototype.setIn = setIn;
+ListPrototype.deleteIn = ListPrototype.removeIn = deleteIn;
+ListPrototype.update = update;
+ListPrototype.updateIn = updateIn;
+ListPrototype.mergeIn = mergeIn;
+ListPrototype.mergeDeepIn = mergeDeepIn;
+ListPrototype.withMutations = withMutations;
+ListPrototype.wasAltered = wasAltered;
+ListPrototype.asImmutable = asImmutable;
+ListPrototype['@@transducer/init'] = ListPrototype.asMutable = asMutable;
+ListPrototype['@@transducer/step'] = function (result, arr) {
+  return result.push(arr);
+};
+ListPrototype['@@transducer/result'] = function (obj) {
+  return obj.asImmutable();
+};
+
+var VNode = function VNode(array, ownerID) {
+  this.array = array;
+  this.ownerID = ownerID;
+};
+
+// TODO: seems like these methods are very similar
+
+VNode.prototype.removeBefore = function removeBefore (ownerID, level, index) {
+  if (
+    (index & ((1 << (level + SHIFT)) - 1)) === 0 ||
+    this.array.length === 0
+  ) {
+    return this;
+  }
+  var originIndex = (index >>> level) & MASK;
+  if (originIndex >= this.array.length) {
+    return new VNode([], ownerID);
+  }
+  var removingFirst = originIndex === 0;
+  var newChild;
+  if (level > 0) {
+    var oldChild = this.array[originIndex];
+    newChild =
+      oldChild && oldChild.removeBefore(ownerID, level - SHIFT, index);
+    if (newChild === oldChild && removingFirst) {
+      return this;
+    }
+  }
+  if (removingFirst && !newChild) {
+    return this;
+  }
+  var editable = editableVNode(this, ownerID);
+  if (!removingFirst) {
+    for (var ii = 0; ii < originIndex; ii++) {
+      editable.array[ii] = undefined;
+    }
+  }
+  if (newChild) {
+    editable.array[originIndex] = newChild;
+  }
+  return editable;
+};
+
+VNode.prototype.removeAfter = function removeAfter (ownerID, level, index) {
+  if (
+    index === (level ? 1 << (level + SHIFT) : SIZE) ||
+    this.array.length === 0
+  ) {
+    return this;
+  }
+  var sizeIndex = ((index - 1) >>> level) & MASK;
+  if (sizeIndex >= this.array.length) {
+    return this;
+  }
+
+  var newChild;
+  if (level > 0) {
+    var oldChild = this.array[sizeIndex];
+    newChild =
+      oldChild && oldChild.removeAfter(ownerID, level - SHIFT, index);
+    if (newChild === oldChild && sizeIndex === this.array.length - 1) {
+      return this;
+    }
+  }
+
+  var editable = editableVNode(this, ownerID);
+  editable.array.splice(sizeIndex + 1);
+  if (newChild) {
+    editable.array[sizeIndex] = newChild;
+  }
+  return editable;
+};
+
+var DONE = {};
+
+function iterateList(list, reverse) {
+  var left = list._origin;
+  var right = list._capacity;
+  var tailPos = getTailOffset(right);
+  var tail = list._tail;
+
+  return iterateNodeOrLeaf(list._root, list._level, 0);
+
+  function iterateNodeOrLeaf(node, level, offset) {
+    return level === 0
+      ? iterateLeaf(node, offset)
+      : iterateNode(node, level, offset);
+  }
+
+  function iterateLeaf(node, offset) {
+    var array = offset === tailPos ? tail && tail.array : node && node.array;
+    var from = offset > left ? 0 : left - offset;
+    var to = right - offset;
+    if (to > SIZE) {
+      to = SIZE;
+    }
+    return function () {
+      if (from === to) {
+        return DONE;
+      }
+      var idx = reverse ? --to : from++;
+      return array && array[idx];
+    };
+  }
+
+  function iterateNode(node, level, offset) {
+    var values;
+    var array = node && node.array;
+    var from = offset > left ? 0 : (left - offset) >> level;
+    var to = ((right - offset) >> level) + 1;
+    if (to > SIZE) {
+      to = SIZE;
+    }
+    return function () {
+      while (true) {
+        if (values) {
+          var value = values();
+          if (value !== DONE) {
+            return value;
+          }
+          values = null;
+        }
+        if (from === to) {
+          return DONE;
+        }
+        var idx = reverse ? --to : from++;
+        values = iterateNodeOrLeaf(
+          array && array[idx],
+          level - SHIFT,
+          offset + (idx << level)
+        );
+      }
+    };
+  }
+}
+
+function makeList(origin, capacity, level, root, tail, ownerID, hash) {
+  var list = Object.create(ListPrototype);
+  list.size = capacity - origin;
+  list._origin = origin;
+  list._capacity = capacity;
+  list._level = level;
+  list._root = root;
+  list._tail = tail;
+  list.__ownerID = ownerID;
+  list.__hash = hash;
+  list.__altered = false;
+  return list;
+}
+
+function emptyList() {
+  return makeList(0, 0, SHIFT);
+}
+
+function updateList(list, index, value) {
+  index = wrapIndex(list, index);
+
+  if (index !== index) {
+    return list;
+  }
+
+  if (index >= list.size || index < 0) {
+    return list.withMutations(function (list) {
+      index < 0
+        ? setListBounds(list, index).set(0, value)
+        : setListBounds(list, 0, index + 1).set(index, value);
+    });
+  }
+
+  index += list._origin;
+
+  var newTail = list._tail;
+  var newRoot = list._root;
+  var didAlter = MakeRef();
+  if (index >= getTailOffset(list._capacity)) {
+    newTail = updateVNode(newTail, list.__ownerID, 0, index, value, didAlter);
+  } else {
+    newRoot = updateVNode(
+      newRoot,
+      list.__ownerID,
+      list._level,
+      index,
+      value,
+      didAlter
+    );
+  }
+
+  if (!didAlter.value) {
+    return list;
+  }
+
+  if (list.__ownerID) {
+    list._root = newRoot;
+    list._tail = newTail;
+    list.__hash = undefined;
+    list.__altered = true;
+    return list;
+  }
+  return makeList(list._origin, list._capacity, list._level, newRoot, newTail);
+}
+
+function updateVNode(node, ownerID, level, index, value, didAlter) {
+  var idx = (index >>> level) & MASK;
+  var nodeHas = node && idx < node.array.length;
+  if (!nodeHas && value === undefined) {
+    return node;
+  }
+
+  var newNode;
+
+  if (level > 0) {
+    var lowerNode = node && node.array[idx];
+    var newLowerNode = updateVNode(
+      lowerNode,
+      ownerID,
+      level - SHIFT,
+      index,
+      value,
+      didAlter
+    );
+    if (newLowerNode === lowerNode) {
+      return node;
+    }
+    newNode = editableVNode(node, ownerID);
+    newNode.array[idx] = newLowerNode;
+    return newNode;
+  }
+
+  if (nodeHas && node.array[idx] === value) {
+    return node;
+  }
+
+  if (didAlter) {
+    SetRef(didAlter);
+  }
+
+  newNode = editableVNode(node, ownerID);
+  if (value === undefined && idx === newNode.array.length - 1) {
+    newNode.array.pop();
+  } else {
+    newNode.array[idx] = value;
+  }
+  return newNode;
+}
+
+function editableVNode(node, ownerID) {
+  if (ownerID && node && ownerID === node.ownerID) {
+    return node;
+  }
+  return new VNode(node ? node.array.slice() : [], ownerID);
+}
+
+function listNodeFor(list, rawIndex) {
+  if (rawIndex >= getTailOffset(list._capacity)) {
+    return list._tail;
+  }
+  if (rawIndex < 1 << (list._level + SHIFT)) {
+    var node = list._root;
+    var level = list._level;
+    while (node && level > 0) {
+      node = node.array[(rawIndex >>> level) & MASK];
+      level -= SHIFT;
+    }
+    return node;
+  }
+}
+
+function setListBounds(list, begin, end) {
+  // Sanitize begin & end using this shorthand for ToInt32(argument)
+  // http://www.ecma-international.org/ecma-262/6.0/#sec-toint32
+  if (begin !== undefined) {
+    begin |= 0;
+  }
+  if (end !== undefined) {
+    end |= 0;
+  }
+  var owner = list.__ownerID || new OwnerID();
+  var oldOrigin = list._origin;
+  var oldCapacity = list._capacity;
+  var newOrigin = oldOrigin + begin;
+  var newCapacity =
+    end === undefined
+      ? oldCapacity
+      : end < 0
+      ? oldCapacity + end
+      : oldOrigin + end;
+  if (newOrigin === oldOrigin && newCapacity === oldCapacity) {
+    return list;
+  }
+
+  // If it's going to end after it starts, it's empty.
+  if (newOrigin >= newCapacity) {
+    return list.clear();
+  }
+
+  var newLevel = list._level;
+  var newRoot = list._root;
+
+  // New origin might need creating a higher root.
+  var offsetShift = 0;
+  while (newOrigin + offsetShift < 0) {
+    newRoot = new VNode(
+      newRoot && newRoot.array.length ? [undefined, newRoot] : [],
+      owner
+    );
+    newLevel += SHIFT;
+    offsetShift += 1 << newLevel;
+  }
+  if (offsetShift) {
+    newOrigin += offsetShift;
+    oldOrigin += offsetShift;
+    newCapacity += offsetShift;
+    oldCapacity += offsetShift;
+  }
+
+  var oldTailOffset = getTailOffset(oldCapacity);
+  var newTailOffset = getTailOffset(newCapacity);
+
+  // New size might need creating a higher root.
+  while (newTailOffset >= 1 << (newLevel + SHIFT)) {
+    newRoot = new VNode(
+      newRoot && newRoot.array.length ? [newRoot] : [],
+      owner
+    );
+    newLevel += SHIFT;
+  }
+
+  // Locate or create the new tail.
+  var oldTail = list._tail;
+  var newTail =
+    newTailOffset < oldTailOffset
+      ? listNodeFor(list, newCapacity - 1)
+      : newTailOffset > oldTailOffset
+      ? new VNode([], owner)
+      : oldTail;
+
+  // Merge Tail into tree.
+  if (
+    oldTail &&
+    newTailOffset > oldTailOffset &&
+    newOrigin < oldCapacity &&
+    oldTail.array.length
+  ) {
+    newRoot = editableVNode(newRoot, owner);
+    var node = newRoot;
+    for (var level = newLevel; level > SHIFT; level -= SHIFT) {
+      var idx = (oldTailOffset >>> level) & MASK;
+      node = node.array[idx] = editableVNode(node.array[idx], owner);
+    }
+    node.array[(oldTailOffset >>> SHIFT) & MASK] = oldTail;
+  }
+
+  // If the size has been reduced, there's a chance the tail needs to be trimmed.
+  if (newCapacity < oldCapacity) {
+    newTail = newTail && newTail.removeAfter(owner, 0, newCapacity);
+  }
+
+  // If the new origin is within the tail, then we do not need a root.
+  if (newOrigin >= newTailOffset) {
+    newOrigin -= newTailOffset;
+    newCapacity -= newTailOffset;
+    newLevel = SHIFT;
+    newRoot = null;
+    newTail = newTail && newTail.removeBefore(owner, 0, newOrigin);
+
+    // Otherwise, if the root has been trimmed, garbage collect.
+  } else if (newOrigin > oldOrigin || newTailOffset < oldTailOffset) {
+    offsetShift = 0;
+
+    // Identify the new top root node of the subtree of the old root.
+    while (newRoot) {
+      var beginIndex = (newOrigin >>> newLevel) & MASK;
+      if ((beginIndex !== newTailOffset >>> newLevel) & MASK) {
+        break;
+      }
+      if (beginIndex) {
+        offsetShift += (1 << newLevel) * beginIndex;
+      }
+      newLevel -= SHIFT;
+      newRoot = newRoot.array[beginIndex];
+    }
+
+    // Trim the new sides of the new root.
+    if (newRoot && newOrigin > oldOrigin) {
+      newRoot = newRoot.removeBefore(owner, newLevel, newOrigin - offsetShift);
+    }
+    if (newRoot && newTailOffset < oldTailOffset) {
+      newRoot = newRoot.removeAfter(
+        owner,
+        newLevel,
+        newTailOffset - offsetShift
+      );
+    }
+    if (offsetShift) {
+      newOrigin -= offsetShift;
+      newCapacity -= offsetShift;
+    }
+  }
+
+  if (list.__ownerID) {
+    list.size = newCapacity - newOrigin;
+    list._origin = newOrigin;
+    list._capacity = newCapacity;
+    list._level = newLevel;
+    list._root = newRoot;
+    list._tail = newTail;
+    list.__hash = undefined;
+    list.__altered = true;
+    return list;
+  }
+  return makeList(newOrigin, newCapacity, newLevel, newRoot, newTail);
+}
+
+function getTailOffset(size) {
+  return size < SIZE ? 0 : ((size - 1) >>> SHIFT) << SHIFT;
+}
+
+var OrderedMap = /*@__PURE__*/(function (Map) {
+  function OrderedMap(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptyOrderedMap()
+      : isOrderedMap(value)
+      ? value
+      : emptyOrderedMap().withMutations(function (map) {
+          var iter = KeyedCollection(value);
+          assertNotInfinite(iter.size);
+          iter.forEach(function (v, k) { return map.set(k, v); });
+        });
+  }
+
+  if ( Map ) OrderedMap.__proto__ = Map;
+  OrderedMap.prototype = Object.create( Map && Map.prototype );
+  OrderedMap.prototype.constructor = OrderedMap;
+
+  OrderedMap.of = function of (/*...values*/) {
+    return this(arguments);
+  };
+
+  OrderedMap.prototype.toString = function toString () {
+    return this.__toString('OrderedMap {', '}');
+  };
+
+  // @pragma Access
+
+  OrderedMap.prototype.get = function get (k, notSetValue) {
+    var index = this._map.get(k);
+    return index !== undefined ? this._list.get(index)[1] : notSetValue;
+  };
+
+  // @pragma Modification
+
+  OrderedMap.prototype.clear = function clear () {
+    if (this.size === 0) {
+      return this;
+    }
+    if (this.__ownerID) {
+      this.size = 0;
+      this._map.clear();
+      this._list.clear();
+      this.__altered = true;
+      return this;
+    }
+    return emptyOrderedMap();
+  };
+
+  OrderedMap.prototype.set = function set (k, v) {
+    return updateOrderedMap(this, k, v);
+  };
+
+  OrderedMap.prototype.remove = function remove (k) {
+    return updateOrderedMap(this, k, NOT_SET);
+  };
+
+  OrderedMap.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    return this._list.__iterate(
+      function (entry) { return entry && fn(entry[1], entry[0], this$1$1); },
+      reverse
+    );
+  };
+
+  OrderedMap.prototype.__iterator = function __iterator (type, reverse) {
+    return this._list.fromEntrySeq().__iterator(type, reverse);
+  };
+
+  OrderedMap.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+    if (ownerID === this.__ownerID) {
+      return this;
+    }
+    var newMap = this._map.__ensureOwner(ownerID);
+    var newList = this._list.__ensureOwner(ownerID);
+    if (!ownerID) {
+      if (this.size === 0) {
+        return emptyOrderedMap();
+      }
+      this.__ownerID = ownerID;
+      this.__altered = false;
+      this._map = newMap;
+      this._list = newList;
+      return this;
+    }
+    return makeOrderedMap(newMap, newList, ownerID, this.__hash);
+  };
+
+  return OrderedMap;
+}(Map));
+
+OrderedMap.isOrderedMap = isOrderedMap;
+
+OrderedMap.prototype[IS_ORDERED_SYMBOL] = true;
+OrderedMap.prototype[DELETE] = OrderedMap.prototype.remove;
+
+function makeOrderedMap(map, list, ownerID, hash) {
+  var omap = Object.create(OrderedMap.prototype);
+  omap.size = map ? map.size : 0;
+  omap._map = map;
+  omap._list = list;
+  omap.__ownerID = ownerID;
+  omap.__hash = hash;
+  omap.__altered = false;
+  return omap;
+}
+
+var EMPTY_ORDERED_MAP;
+function emptyOrderedMap() {
+  return (
+    EMPTY_ORDERED_MAP ||
+    (EMPTY_ORDERED_MAP = makeOrderedMap(emptyMap(), emptyList()))
+  );
+}
+
+function updateOrderedMap(omap, k, v) {
+  var map = omap._map;
+  var list = omap._list;
+  var i = map.get(k);
+  var has = i !== undefined;
+  var newMap;
+  var newList;
+  if (v === NOT_SET) {
+    // removed
+    if (!has) {
+      return omap;
+    }
+    if (list.size >= SIZE && list.size >= map.size * 2) {
+      newList = list.filter(function (entry, idx) { return entry !== undefined && i !== idx; });
+      newMap = newList
+        .toKeyedSeq()
+        .map(function (entry) { return entry[0]; })
+        .flip()
+        .toMap();
+      if (omap.__ownerID) {
+        newMap.__ownerID = newList.__ownerID = omap.__ownerID;
+      }
+    } else {
+      newMap = map.remove(k);
+      newList = i === list.size - 1 ? list.pop() : list.set(i, undefined);
+    }
+  } else if (has) {
+    if (v === list.get(i)[1]) {
+      return omap;
+    }
+    newMap = map;
+    newList = list.set(i, [k, v]);
+  } else {
+    newMap = map.set(k, list.size);
+    newList = list.set(list.size, [k, v]);
+  }
+  if (omap.__ownerID) {
+    omap.size = newMap.size;
+    omap._map = newMap;
+    omap._list = newList;
+    omap.__hash = undefined;
+    omap.__altered = true;
+    return omap;
+  }
+  return makeOrderedMap(newMap, newList);
+}
+
+var IS_STACK_SYMBOL = '@@__IMMUTABLE_STACK__@@';
+
+function isStack(maybeStack) {
+  return Boolean(maybeStack && maybeStack[IS_STACK_SYMBOL]);
+}
+
+var Stack = /*@__PURE__*/(function (IndexedCollection) {
+  function Stack(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptyStack()
+      : isStack(value)
+      ? value
+      : emptyStack().pushAll(value);
+  }
+
+  if ( IndexedCollection ) Stack.__proto__ = IndexedCollection;
+  Stack.prototype = Object.create( IndexedCollection && IndexedCollection.prototype );
+  Stack.prototype.constructor = Stack;
+
+  Stack.of = function of (/*...values*/) {
+    return this(arguments);
+  };
+
+  Stack.prototype.toString = function toString () {
+    return this.__toString('Stack [', ']');
+  };
+
+  // @pragma Access
+
+  Stack.prototype.get = function get (index, notSetValue) {
+    var head = this._head;
+    index = wrapIndex(this, index);
+    while (head && index--) {
+      head = head.next;
+    }
+    return head ? head.value : notSetValue;
+  };
+
+  Stack.prototype.peek = function peek () {
+    return this._head && this._head.value;
+  };
+
+  // @pragma Modification
+
+  Stack.prototype.push = function push (/*...values*/) {
+    var arguments$1 = arguments;
+
+    if (arguments.length === 0) {
+      return this;
+    }
+    var newSize = this.size + arguments.length;
+    var head = this._head;
+    for (var ii = arguments.length - 1; ii >= 0; ii--) {
+      head = {
+        value: arguments$1[ii],
+        next: head,
+      };
+    }
+    if (this.__ownerID) {
+      this.size = newSize;
+      this._head = head;
+      this.__hash = undefined;
+      this.__altered = true;
+      return this;
+    }
+    return makeStack(newSize, head);
+  };
+
+  Stack.prototype.pushAll = function pushAll (iter) {
+    iter = IndexedCollection(iter);
+    if (iter.size === 0) {
+      return this;
+    }
+    if (this.size === 0 && isStack(iter)) {
+      return iter;
+    }
+    assertNotInfinite(iter.size);
+    var newSize = this.size;
+    var head = this._head;
+    iter.__iterate(function (value) {
+      newSize++;
+      head = {
+        value: value,
+        next: head,
+      };
+    }, /* reverse */ true);
+    if (this.__ownerID) {
+      this.size = newSize;
+      this._head = head;
+      this.__hash = undefined;
+      this.__altered = true;
+      return this;
+    }
+    return makeStack(newSize, head);
+  };
+
+  Stack.prototype.pop = function pop () {
+    return this.slice(1);
+  };
+
+  Stack.prototype.clear = function clear () {
+    if (this.size === 0) {
+      return this;
+    }
+    if (this.__ownerID) {
+      this.size = 0;
+      this._head = undefined;
+      this.__hash = undefined;
+      this.__altered = true;
+      return this;
+    }
+    return emptyStack();
+  };
+
+  Stack.prototype.slice = function slice (begin, end) {
+    if (wholeSlice(begin, end, this.size)) {
+      return this;
+    }
+    var resolvedBegin = resolveBegin(begin, this.size);
+    var resolvedEnd = resolveEnd(end, this.size);
+    if (resolvedEnd !== this.size) {
+      // super.slice(begin, end);
+      return IndexedCollection.prototype.slice.call(this, begin, end);
+    }
+    var newSize = this.size - resolvedBegin;
+    var head = this._head;
+    while (resolvedBegin--) {
+      head = head.next;
+    }
+    if (this.__ownerID) {
+      this.size = newSize;
+      this._head = head;
+      this.__hash = undefined;
+      this.__altered = true;
+      return this;
+    }
+    return makeStack(newSize, head);
+  };
+
+  // @pragma Mutability
+
+  Stack.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+    if (ownerID === this.__ownerID) {
+      return this;
+    }
+    if (!ownerID) {
+      if (this.size === 0) {
+        return emptyStack();
+      }
+      this.__ownerID = ownerID;
+      this.__altered = false;
+      return this;
+    }
+    return makeStack(this.size, this._head, ownerID, this.__hash);
+  };
+
+  // @pragma Iteration
+
+  Stack.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    if (reverse) {
+      return new ArraySeq(this.toArray()).__iterate(
+        function (v, k) { return fn(v, k, this$1$1); },
+        reverse
+      );
+    }
+    var iterations = 0;
+    var node = this._head;
+    while (node) {
+      if (fn(node.value, iterations++, this) === false) {
+        break;
+      }
+      node = node.next;
+    }
+    return iterations;
+  };
+
+  Stack.prototype.__iterator = function __iterator (type, reverse) {
+    if (reverse) {
+      return new ArraySeq(this.toArray()).__iterator(type, reverse);
+    }
+    var iterations = 0;
+    var node = this._head;
+    return new Iterator(function () {
+      if (node) {
+        var value = node.value;
+        node = node.next;
+        return iteratorValue(type, iterations++, value);
+      }
+      return iteratorDone();
+    });
+  };
+
+  return Stack;
+}(IndexedCollection));
+
+Stack.isStack = isStack;
+
+var StackPrototype = Stack.prototype;
+StackPrototype[IS_STACK_SYMBOL] = true;
+StackPrototype.shift = StackPrototype.pop;
+StackPrototype.unshift = StackPrototype.push;
+StackPrototype.unshiftAll = StackPrototype.pushAll;
+StackPrototype.withMutations = withMutations;
+StackPrototype.wasAltered = wasAltered;
+StackPrototype.asImmutable = asImmutable;
+StackPrototype['@@transducer/init'] = StackPrototype.asMutable = asMutable;
+StackPrototype['@@transducer/step'] = function (result, arr) {
+  return result.unshift(arr);
+};
+StackPrototype['@@transducer/result'] = function (obj) {
+  return obj.asImmutable();
+};
+
+function makeStack(size, head, ownerID, hash) {
+  var map = Object.create(StackPrototype);
+  map.size = size;
+  map._head = head;
+  map.__ownerID = ownerID;
+  map.__hash = hash;
+  map.__altered = false;
+  return map;
+}
+
+var EMPTY_STACK;
+function emptyStack() {
+  return EMPTY_STACK || (EMPTY_STACK = makeStack(0));
+}
+
+var IS_SET_SYMBOL = '@@__IMMUTABLE_SET__@@';
+
+function isSet(maybeSet) {
+  return Boolean(maybeSet && maybeSet[IS_SET_SYMBOL]);
+}
+
+function isOrderedSet(maybeOrderedSet) {
+  return isSet(maybeOrderedSet) && isOrdered(maybeOrderedSet);
+}
+
+function deepEqual(a, b) {
+  if (a === b) {
+    return true;
+  }
+
+  if (
+    !isCollection(b) ||
+    (a.size !== undefined && b.size !== undefined && a.size !== b.size) ||
+    (a.__hash !== undefined &&
+      b.__hash !== undefined &&
+      a.__hash !== b.__hash) ||
+    isKeyed(a) !== isKeyed(b) ||
+    isIndexed(a) !== isIndexed(b) ||
+    isOrdered(a) !== isOrdered(b)
+  ) {
+    return false;
+  }
+
+  if (a.size === 0 && b.size === 0) {
+    return true;
+  }
+
+  var notAssociative = !isAssociative(a);
+
+  if (isOrdered(a)) {
+    var entries = a.entries();
+    return (
+      b.every(function (v, k) {
+        var entry = entries.next().value;
+        return entry && is(entry[1], v) && (notAssociative || is(entry[0], k));
+      }) && entries.next().done
+    );
+  }
+
+  var flipped = false;
+
+  if (a.size === undefined) {
+    if (b.size === undefined) {
+      if (typeof a.cacheResult === 'function') {
+        a.cacheResult();
+      }
+    } else {
+      flipped = true;
+      var _ = a;
+      a = b;
+      b = _;
+    }
+  }
+
+  var allEqual = true;
+  var bSize = b.__iterate(function (v, k) {
+    if (
+      notAssociative
+        ? !a.has(v)
+        : flipped
+        ? !is(v, a.get(k, NOT_SET))
+        : !is(a.get(k, NOT_SET), v)
+    ) {
+      allEqual = false;
+      return false;
+    }
+  });
+
+  return allEqual && a.size === bSize;
+}
+
+/**
+ * Contributes additional methods to a constructor
+ */
+function mixin(ctor, methods) {
+  var keyCopier = function (key) {
+    ctor.prototype[key] = methods[key];
+  };
+  Object.keys(methods).forEach(keyCopier);
+  Object.getOwnPropertySymbols &&
+    Object.getOwnPropertySymbols(methods).forEach(keyCopier);
+  return ctor;
+}
+
+function toJS(value) {
+  if (!value || typeof value !== 'object') {
+    return value;
+  }
+  if (!isCollection(value)) {
+    if (!isDataStructure(value)) {
+      return value;
+    }
+    value = Seq(value);
+  }
+  if (isKeyed(value)) {
+    var result$1 = {};
+    value.__iterate(function (v, k) {
+      result$1[k] = toJS(v);
+    });
+    return result$1;
+  }
+  var result = [];
+  value.__iterate(function (v) {
+    result.push(toJS(v));
+  });
+  return result;
+}
+
+var Set = /*@__PURE__*/(function (SetCollection) {
+  function Set(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptySet()
+      : isSet(value) && !isOrdered(value)
+      ? value
+      : emptySet().withMutations(function (set) {
+          var iter = SetCollection(value);
+          assertNotInfinite(iter.size);
+          iter.forEach(function (v) { return set.add(v); });
+        });
+  }
+
+  if ( SetCollection ) Set.__proto__ = SetCollection;
+  Set.prototype = Object.create( SetCollection && SetCollection.prototype );
+  Set.prototype.constructor = Set;
+
+  Set.of = function of (/*...values*/) {
+    return this(arguments);
+  };
+
+  Set.fromKeys = function fromKeys (value) {
+    return this(KeyedCollection(value).keySeq());
+  };
+
+  Set.intersect = function intersect (sets) {
+    sets = Collection(sets).toArray();
+    return sets.length
+      ? SetPrototype.intersect.apply(Set(sets.pop()), sets)
+      : emptySet();
+  };
+
+  Set.union = function union (sets) {
+    sets = Collection(sets).toArray();
+    return sets.length
+      ? SetPrototype.union.apply(Set(sets.pop()), sets)
+      : emptySet();
+  };
+
+  Set.prototype.toString = function toString () {
+    return this.__toString('Set {', '}');
+  };
+
+  // @pragma Access
+
+  Set.prototype.has = function has (value) {
+    return this._map.has(value);
+  };
+
+  // @pragma Modification
+
+  Set.prototype.add = function add (value) {
+    return updateSet(this, this._map.set(value, value));
+  };
+
+  Set.prototype.remove = function remove (value) {
+    return updateSet(this, this._map.remove(value));
+  };
+
+  Set.prototype.clear = function clear () {
+    return updateSet(this, this._map.clear());
+  };
+
+  // @pragma Composition
+
+  Set.prototype.map = function map (mapper, context) {
+    var this$1$1 = this;
+
+    // keep track if the set is altered by the map function
+    var didChanges = false;
+
+    var newMap = updateSet(
+      this,
+      this._map.mapEntries(function (ref) {
+        var v = ref[1];
+
+        var mapped = mapper.call(context, v, v, this$1$1);
+
+        if (mapped !== v) {
+          didChanges = true;
+        }
+
+        return [mapped, mapped];
+      }, context)
+    );
+
+    return didChanges ? newMap : this;
+  };
+
+  Set.prototype.union = function union () {
+    var iters = [], len = arguments.length;
+    while ( len-- ) iters[ len ] = arguments[ len ];
+
+    iters = iters.filter(function (x) { return x.size !== 0; });
+    if (iters.length === 0) {
+      return this;
+    }
+    if (this.size === 0 && !this.__ownerID && iters.length === 1) {
+      return this.constructor(iters[0]);
+    }
+    return this.withMutations(function (set) {
+      for (var ii = 0; ii < iters.length; ii++) {
+        if (typeof iters[ii] === 'string') {
+          set.add(iters[ii]);
+        } else {
+          SetCollection(iters[ii]).forEach(function (value) { return set.add(value); });
+        }
+      }
+    });
+  };
+
+  Set.prototype.intersect = function intersect () {
+    var iters = [], len = arguments.length;
+    while ( len-- ) iters[ len ] = arguments[ len ];
+
+    if (iters.length === 0) {
+      return this;
+    }
+    iters = iters.map(function (iter) { return SetCollection(iter); });
+    var toRemove = [];
+    this.forEach(function (value) {
+      if (!iters.every(function (iter) { return iter.includes(value); })) {
+        toRemove.push(value);
+      }
+    });
+    return this.withMutations(function (set) {
+      toRemove.forEach(function (value) {
+        set.remove(value);
+      });
+    });
+  };
+
+  Set.prototype.subtract = function subtract () {
+    var iters = [], len = arguments.length;
+    while ( len-- ) iters[ len ] = arguments[ len ];
+
+    if (iters.length === 0) {
+      return this;
+    }
+    iters = iters.map(function (iter) { return SetCollection(iter); });
+    var toRemove = [];
+    this.forEach(function (value) {
+      if (iters.some(function (iter) { return iter.includes(value); })) {
+        toRemove.push(value);
+      }
+    });
+    return this.withMutations(function (set) {
+      toRemove.forEach(function (value) {
+        set.remove(value);
+      });
+    });
+  };
+
+  Set.prototype.sort = function sort (comparator) {
+    // Late binding
+    return OrderedSet(sortFactory(this, comparator));
+  };
+
+  Set.prototype.sortBy = function sortBy (mapper, comparator) {
+    // Late binding
+    return OrderedSet(sortFactory(this, comparator, mapper));
+  };
+
+  Set.prototype.wasAltered = function wasAltered () {
+    return this._map.wasAltered();
+  };
+
+  Set.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    return this._map.__iterate(function (k) { return fn(k, k, this$1$1); }, reverse);
+  };
+
+  Set.prototype.__iterator = function __iterator (type, reverse) {
+    return this._map.__iterator(type, reverse);
+  };
+
+  Set.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+    if (ownerID === this.__ownerID) {
+      return this;
+    }
+    var newMap = this._map.__ensureOwner(ownerID);
+    if (!ownerID) {
+      if (this.size === 0) {
+        return this.__empty();
+      }
+      this.__ownerID = ownerID;
+      this._map = newMap;
+      return this;
+    }
+    return this.__make(newMap, ownerID);
+  };
+
+  return Set;
+}(SetCollection));
+
+Set.isSet = isSet;
+
+var SetPrototype = Set.prototype;
+SetPrototype[IS_SET_SYMBOL] = true;
+SetPrototype[DELETE] = SetPrototype.remove;
+SetPrototype.merge = SetPrototype.concat = SetPrototype.union;
+SetPrototype.withMutations = withMutations;
+SetPrototype.asImmutable = asImmutable;
+SetPrototype['@@transducer/init'] = SetPrototype.asMutable = asMutable;
+SetPrototype['@@transducer/step'] = function (result, arr) {
+  return result.add(arr);
+};
+SetPrototype['@@transducer/result'] = function (obj) {
+  return obj.asImmutable();
+};
+
+SetPrototype.__empty = emptySet;
+SetPrototype.__make = makeSet;
+
+function updateSet(set, newMap) {
+  if (set.__ownerID) {
+    set.size = newMap.size;
+    set._map = newMap;
+    return set;
+  }
+  return newMap === set._map
+    ? set
+    : newMap.size === 0
+    ? set.__empty()
+    : set.__make(newMap);
+}
+
+function makeSet(map, ownerID) {
+  var set = Object.create(SetPrototype);
+  set.size = map ? map.size : 0;
+  set._map = map;
+  set.__ownerID = ownerID;
+  return set;
+}
+
+var EMPTY_SET;
+function emptySet() {
+  return EMPTY_SET || (EMPTY_SET = makeSet(emptyMap()));
+}
+
+/**
+ * Returns a lazy seq of nums from start (inclusive) to end
+ * (exclusive), by step, where start defaults to 0, step to 1, and end to
+ * infinity. When start is equal to end, returns empty list.
+ */
+var Range = /*@__PURE__*/(function (IndexedSeq) {
+  function Range(start, end, step) {
+    if ( step === void 0 ) step = 1;
+
+    if (!(this instanceof Range)) {
+      // eslint-disable-next-line no-constructor-return
+      return new Range(start, end, step);
+    }
+    invariant(step !== 0, 'Cannot step a Range by 0');
+    invariant(
+      start !== undefined,
+      'You must define a start value when using Range'
+    );
+    invariant(
+      end !== undefined,
+      'You must define an end value when using Range'
+    );
+
+    step = Math.abs(step);
+    if (end < start) {
+      step = -step;
+    }
+    this._start = start;
+    this._end = end;
+    this._step = step;
+    this.size = Math.max(0, Math.ceil((end - start) / step - 1) + 1);
+    if (this.size === 0) {
+      if (EMPTY_RANGE) {
+        // eslint-disable-next-line no-constructor-return
+        return EMPTY_RANGE;
+      }
+      // eslint-disable-next-line @typescript-eslint/no-this-alias
+      EMPTY_RANGE = this;
+    }
+  }
+
+  if ( IndexedSeq ) Range.__proto__ = IndexedSeq;
+  Range.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+  Range.prototype.constructor = Range;
+
+  Range.prototype.toString = function toString () {
+    if (this.size === 0) {
+      return 'Range []';
+    }
+    return (
+      'Range [ ' +
+      this._start +
+      '...' +
+      this._end +
+      (this._step !== 1 ? ' by ' + this._step : '') +
+      ' ]'
+    );
+  };
+
+  Range.prototype.get = function get (index, notSetValue) {
+    return this.has(index)
+      ? this._start + wrapIndex(this, index) * this._step
+      : notSetValue;
+  };
+
+  Range.prototype.includes = function includes (searchValue) {
+    var possibleIndex = (searchValue - this._start) / this._step;
+    return (
+      possibleIndex >= 0 &&
+      possibleIndex < this.size &&
+      possibleIndex === Math.floor(possibleIndex)
+    );
+  };
+
+  Range.prototype.slice = function slice (begin, end) {
+    if (wholeSlice(begin, end, this.size)) {
+      return this;
+    }
+    begin = resolveBegin(begin, this.size);
+    end = resolveEnd(end, this.size);
+    if (end <= begin) {
+      return new Range(0, 0);
+    }
+    return new Range(
+      this.get(begin, this._end),
+      this.get(end, this._end),
+      this._step
+    );
+  };
+
+  Range.prototype.indexOf = function indexOf (searchValue) {
+    var offsetValue = searchValue - this._start;
+    if (offsetValue % this._step === 0) {
+      var index = offsetValue / this._step;
+      if (index >= 0 && index < this.size) {
+        return index;
+      }
+    }
+    return -1;
+  };
+
+  Range.prototype.lastIndexOf = function lastIndexOf (searchValue) {
+    return this.indexOf(searchValue);
+  };
+
+  Range.prototype.__iterate = function __iterate (fn, reverse) {
+    var size = this.size;
+    var step = this._step;
+    var value = reverse ? this._start + (size - 1) * step : this._start;
+    var i = 0;
+    while (i !== size) {
+      if (fn(value, reverse ? size - ++i : i++, this) === false) {
+        break;
+      }
+      value += reverse ? -step : step;
+    }
+    return i;
+  };
+
+  Range.prototype.__iterator = function __iterator (type, reverse) {
+    var size = this.size;
+    var step = this._step;
+    var value = reverse ? this._start + (size - 1) * step : this._start;
+    var i = 0;
+    return new Iterator(function () {
+      if (i === size) {
+        return iteratorDone();
+      }
+      var v = value;
+      value += reverse ? -step : step;
+      return iteratorValue(type, reverse ? size - ++i : i++, v);
+    });
+  };
+
+  Range.prototype.equals = function equals (other) {
+    return other instanceof Range
+      ? this._start === other._start &&
+          this._end === other._end &&
+          this._step === other._step
+      : deepEqual(this, other);
+  };
+
+  return Range;
+}(IndexedSeq));
+
+var EMPTY_RANGE;
+
+function getIn$1(collection, searchKeyPath, notSetValue) {
+  var keyPath = coerceKeyPath(searchKeyPath);
+  var i = 0;
+  while (i !== keyPath.length) {
+    collection = get(collection, keyPath[i++], NOT_SET);
+    if (collection === NOT_SET) {
+      return notSetValue;
+    }
+  }
+  return collection;
+}
+
+function getIn(searchKeyPath, notSetValue) {
+  return getIn$1(this, searchKeyPath, notSetValue);
+}
+
+function hasIn$1(collection, keyPath) {
+  return getIn$1(collection, keyPath, NOT_SET) !== NOT_SET;
+}
+
+function hasIn(searchKeyPath) {
+  return hasIn$1(this, searchKeyPath);
+}
+
+function toObject() {
+  assertNotInfinite(this.size);
+  var object = {};
+  this.__iterate(function (v, k) {
+    object[k] = v;
+  });
+  return object;
+}
+
+Collection.Iterator = Iterator;
+
+mixin(Collection, {
+  // ### Conversion to other types
+
+  toArray: function toArray() {
+    assertNotInfinite(this.size);
+    var array = new Array(this.size || 0);
+    var useTuples = isKeyed(this);
+    var i = 0;
+    this.__iterate(function (v, k) {
+      // Keyed collections produce an array of tuples.
+      array[i++] = useTuples ? [k, v] : v;
+    });
+    return array;
+  },
+
+  toIndexedSeq: function toIndexedSeq() {
+    return new ToIndexedSequence(this);
+  },
+
+  toJS: function toJS$1() {
+    return toJS(this);
+  },
+
+  toKeyedSeq: function toKeyedSeq() {
+    return new ToKeyedSequence(this, true);
+  },
+
+  toMap: function toMap() {
+    // Use Late Binding here to solve the circular dependency.
+    return Map(this.toKeyedSeq());
+  },
+
+  toObject: toObject,
+
+  toOrderedMap: function toOrderedMap() {
+    // Use Late Binding here to solve the circular dependency.
+    return OrderedMap(this.toKeyedSeq());
+  },
+
+  toOrderedSet: function toOrderedSet() {
+    // Use Late Binding here to solve the circular dependency.
+    return OrderedSet(isKeyed(this) ? this.valueSeq() : this);
+  },
+
+  toSet: function toSet() {
+    // Use Late Binding here to solve the circular dependency.
+    return Set(isKeyed(this) ? this.valueSeq() : this);
+  },
+
+  toSetSeq: function toSetSeq() {
+    return new ToSetSequence(this);
+  },
+
+  toSeq: function toSeq() {
+    return isIndexed(this)
+      ? this.toIndexedSeq()
+      : isKeyed(this)
+      ? this.toKeyedSeq()
+      : this.toSetSeq();
+  },
+
+  toStack: function toStack() {
+    // Use Late Binding here to solve the circular dependency.
+    return Stack(isKeyed(this) ? this.valueSeq() : this);
+  },
+
+  toList: function toList() {
+    // Use Late Binding here to solve the circular dependency.
+    return List(isKeyed(this) ? this.valueSeq() : this);
+  },
+
+  // ### Common JavaScript methods and properties
+
+  toString: function toString() {
+    return '[Collection]';
+  },
+
+  __toString: function __toString(head, tail) {
+    if (this.size === 0) {
+      return head + tail;
+    }
+    return (
+      head +
+      ' ' +
+      this.toSeq().map(this.__toStringMapper).join(', ') +
+      ' ' +
+      tail
+    );
+  },
+
+  // ### ES6 Collection methods (ES6 Array and Map)
+
+  concat: function concat() {
+    var values = [], len = arguments.length;
+    while ( len-- ) values[ len ] = arguments[ len ];
+
+    return reify(this, concatFactory(this, values));
+  },
+
+  includes: function includes(searchValue) {
+    return this.some(function (value) { return is(value, searchValue); });
+  },
+
+  entries: function entries() {
+    return this.__iterator(ITERATE_ENTRIES);
+  },
+
+  every: function every(predicate, context) {
+    assertNotInfinite(this.size);
+    var returnValue = true;
+    this.__iterate(function (v, k, c) {
+      if (!predicate.call(context, v, k, c)) {
+        returnValue = false;
+        return false;
+      }
+    });
+    return returnValue;
+  },
+
+  filter: function filter(predicate, context) {
+    return reify(this, filterFactory(this, predicate, context, true));
+  },
+
+  partition: function partition(predicate, context) {
+    return partitionFactory(this, predicate, context);
+  },
+
+  find: function find(predicate, context, notSetValue) {
+    var entry = this.findEntry(predicate, context);
+    return entry ? entry[1] : notSetValue;
+  },
+
+  forEach: function forEach(sideEffect, context) {
+    assertNotInfinite(this.size);
+    return this.__iterate(context ? sideEffect.bind(context) : sideEffect);
+  },
+
+  join: function join(separator) {
+    assertNotInfinite(this.size);
+    separator = separator !== undefined ? '' + separator : ',';
+    var joined = '';
+    var isFirst = true;
+    this.__iterate(function (v) {
+      isFirst ? (isFirst = false) : (joined += separator);
+      joined += v !== null && v !== undefined ? v.toString() : '';
+    });
+    return joined;
+  },
+
+  keys: function keys() {
+    return this.__iterator(ITERATE_KEYS);
+  },
+
+  map: function map(mapper, context) {
+    return reify(this, mapFactory(this, mapper, context));
+  },
+
+  reduce: function reduce$1(reducer, initialReduction, context) {
+    return reduce(
+      this,
+      reducer,
+      initialReduction,
+      context,
+      arguments.length < 2,
+      false
+    );
+  },
+
+  reduceRight: function reduceRight(reducer, initialReduction, context) {
+    return reduce(
+      this,
+      reducer,
+      initialReduction,
+      context,
+      arguments.length < 2,
+      true
+    );
+  },
+
+  reverse: function reverse() {
+    return reify(this, reverseFactory(this, true));
+  },
+
+  slice: function slice(begin, end) {
+    return reify(this, sliceFactory(this, begin, end, true));
+  },
+
+  some: function some(predicate, context) {
+    assertNotInfinite(this.size);
+    var returnValue = false;
+    this.__iterate(function (v, k, c) {
+      if (predicate.call(context, v, k, c)) {
+        returnValue = true;
+        return false;
+      }
+    });
+    return returnValue;
+  },
+
+  sort: function sort(comparator) {
+    return reify(this, sortFactory(this, comparator));
+  },
+
+  values: function values() {
+    return this.__iterator(ITERATE_VALUES);
+  },
+
+  // ### More sequential methods
+
+  butLast: function butLast() {
+    return this.slice(0, -1);
+  },
+
+  isEmpty: function isEmpty() {
+    return this.size !== undefined ? this.size === 0 : !this.some(function () { return true; });
+  },
+
+  count: function count(predicate, context) {
+    return ensureSize(
+      predicate ? this.toSeq().filter(predicate, context) : this
+    );
+  },
+
+  countBy: function countBy(grouper, context) {
+    return countByFactory(this, grouper, context);
+  },
+
+  equals: function equals(other) {
+    return deepEqual(this, other);
+  },
+
+  entrySeq: function entrySeq() {
+    // eslint-disable-next-line @typescript-eslint/no-this-alias
+    var collection = this;
+    if (collection._cache) {
+      // We cache as an entries array, so we can just return the cache!
+      return new ArraySeq(collection._cache);
+    }
+    var entriesSequence = collection.toSeq().map(entryMapper).toIndexedSeq();
+    entriesSequence.fromEntrySeq = function () { return collection.toSeq(); };
+    return entriesSequence;
+  },
+
+  filterNot: function filterNot(predicate, context) {
+    return this.filter(not(predicate), context);
+  },
+
+  findEntry: function findEntry(predicate, context, notSetValue) {
+    var found = notSetValue;
+    this.__iterate(function (v, k, c) {
+      if (predicate.call(context, v, k, c)) {
+        found = [k, v];
+        return false;
+      }
+    });
+    return found;
+  },
+
+  findKey: function findKey(predicate, context) {
+    var entry = this.findEntry(predicate, context);
+    return entry && entry[0];
+  },
+
+  findLast: function findLast(predicate, context, notSetValue) {
+    return this.toKeyedSeq().reverse().find(predicate, context, notSetValue);
+  },
+
+  findLastEntry: function findLastEntry(predicate, context, notSetValue) {
+    return this.toKeyedSeq()
+      .reverse()
+      .findEntry(predicate, context, notSetValue);
+  },
+
+  findLastKey: function findLastKey(predicate, context) {
+    return this.toKeyedSeq().reverse().findKey(predicate, context);
+  },
+
+  first: function first(notSetValue) {
+    return this.find(returnTrue, null, notSetValue);
+  },
+
+  flatMap: function flatMap(mapper, context) {
+    return reify(this, flatMapFactory(this, mapper, context));
+  },
+
+  flatten: function flatten(depth) {
+    return reify(this, flattenFactory(this, depth, true));
+  },
+
+  fromEntrySeq: function fromEntrySeq() {
+    return new FromEntriesSequence(this);
+  },
+
+  get: function get(searchKey, notSetValue) {
+    return this.find(function (_, key) { return is(key, searchKey); }, undefined, notSetValue);
+  },
+
+  getIn: getIn,
+
+  groupBy: function groupBy(grouper, context) {
+    return groupByFactory(this, grouper, context);
+  },
+
+  has: function has(searchKey) {
+    return this.get(searchKey, NOT_SET) !== NOT_SET;
+  },
+
+  hasIn: hasIn,
+
+  isSubset: function isSubset(iter) {
+    iter = typeof iter.includes === 'function' ? iter : Collection(iter);
+    return this.every(function (value) { return iter.includes(value); });
+  },
+
+  isSuperset: function isSuperset(iter) {
+    iter = typeof iter.isSubset === 'function' ? iter : Collection(iter);
+    return iter.isSubset(this);
+  },
+
+  keyOf: function keyOf(searchValue) {
+    return this.findKey(function (value) { return is(value, searchValue); });
+  },
+
+  keySeq: function keySeq() {
+    return this.toSeq().map(keyMapper).toIndexedSeq();
+  },
+
+  last: function last(notSetValue) {
+    return this.toSeq().reverse().first(notSetValue);
+  },
+
+  lastKeyOf: function lastKeyOf(searchValue) {
+    return this.toKeyedSeq().reverse().keyOf(searchValue);
+  },
+
+  max: function max(comparator) {
+    return maxFactory(this, comparator);
+  },
+
+  maxBy: function maxBy(mapper, comparator) {
+    return maxFactory(this, comparator, mapper);
+  },
+
+  min: function min(comparator) {
+    return maxFactory(
+      this,
+      comparator ? neg(comparator) : defaultNegComparator
+    );
+  },
+
+  minBy: function minBy(mapper, comparator) {
+    return maxFactory(
+      this,
+      comparator ? neg(comparator) : defaultNegComparator,
+      mapper
+    );
+  },
+
+  rest: function rest() {
+    return this.slice(1);
+  },
+
+  skip: function skip(amount) {
+    return amount === 0 ? this : this.slice(Math.max(0, amount));
+  },
+
+  skipLast: function skipLast(amount) {
+    return amount === 0 ? this : this.slice(0, -Math.max(0, amount));
+  },
+
+  skipWhile: function skipWhile(predicate, context) {
+    return reify(this, skipWhileFactory(this, predicate, context, true));
+  },
+
+  skipUntil: function skipUntil(predicate, context) {
+    return this.skipWhile(not(predicate), context);
+  },
+
+  sortBy: function sortBy(mapper, comparator) {
+    return reify(this, sortFactory(this, comparator, mapper));
+  },
+
+  take: function take(amount) {
+    return this.slice(0, Math.max(0, amount));
+  },
+
+  takeLast: function takeLast(amount) {
+    return this.slice(-Math.max(0, amount));
+  },
+
+  takeWhile: function takeWhile(predicate, context) {
+    return reify(this, takeWhileFactory(this, predicate, context));
+  },
+
+  takeUntil: function takeUntil(predicate, context) {
+    return this.takeWhile(not(predicate), context);
+  },
+
+  update: function update(fn) {
+    return fn(this);
+  },
+
+  valueSeq: function valueSeq() {
+    return this.toIndexedSeq();
+  },
+
+  // ### Hashable Object
+
+  hashCode: function hashCode() {
+    return this.__hash || (this.__hash = hashCollection(this));
+  },
+
+  // ### Internal
+
+  // abstract __iterate(fn, reverse)
+
+  // abstract __iterator(type, reverse)
+});
+
+var CollectionPrototype = Collection.prototype;
+CollectionPrototype[IS_COLLECTION_SYMBOL] = true;
+CollectionPrototype[ITERATOR_SYMBOL] = CollectionPrototype.values;
+CollectionPrototype.toJSON = CollectionPrototype.toArray;
+CollectionPrototype.__toStringMapper = quoteString;
+CollectionPrototype.inspect = CollectionPrototype.toSource = function () {
+  return this.toString();
+};
+CollectionPrototype.chain = CollectionPrototype.flatMap;
+CollectionPrototype.contains = CollectionPrototype.includes;
+
+mixin(KeyedCollection, {
+  // ### More sequential methods
+
+  flip: function flip() {
+    return reify(this, flipFactory(this));
+  },
+
+  mapEntries: function mapEntries(mapper, context) {
+    var this$1$1 = this;
+
+    var iterations = 0;
+    return reify(
+      this,
+      this.toSeq()
+        .map(function (v, k) { return mapper.call(context, [k, v], iterations++, this$1$1); })
+        .fromEntrySeq()
+    );
+  },
+
+  mapKeys: function mapKeys(mapper, context) {
+    var this$1$1 = this;
+
+    return reify(
+      this,
+      this.toSeq()
+        .flip()
+        .map(function (k, v) { return mapper.call(context, k, v, this$1$1); })
+        .flip()
+    );
+  },
+});
+
+var KeyedCollectionPrototype = KeyedCollection.prototype;
+KeyedCollectionPrototype[IS_KEYED_SYMBOL] = true;
+KeyedCollectionPrototype[ITERATOR_SYMBOL] = CollectionPrototype.entries;
+KeyedCollectionPrototype.toJSON = toObject;
+KeyedCollectionPrototype.__toStringMapper = function (v, k) { return quoteString(k) + ': ' + quoteString(v); };
+
+mixin(IndexedCollection, {
+  // ### Conversion to other types
+
+  toKeyedSeq: function toKeyedSeq() {
+    return new ToKeyedSequence(this, false);
+  },
+
+  // ### ES6 Collection methods (ES6 Array and Map)
+
+  filter: function filter(predicate, context) {
+    return reify(this, filterFactory(this, predicate, context, false));
+  },
+
+  findIndex: function findIndex(predicate, context) {
+    var entry = this.findEntry(predicate, context);
+    return entry ? entry[0] : -1;
+  },
+
+  indexOf: function indexOf(searchValue) {
+    var key = this.keyOf(searchValue);
+    return key === undefined ? -1 : key;
+  },
+
+  lastIndexOf: function lastIndexOf(searchValue) {
+    var key = this.lastKeyOf(searchValue);
+    return key === undefined ? -1 : key;
+  },
+
+  reverse: function reverse() {
+    return reify(this, reverseFactory(this, false));
+  },
+
+  slice: function slice(begin, end) {
+    return reify(this, sliceFactory(this, begin, end, false));
+  },
+
+  splice: function splice(index, removeNum /*, ...values*/) {
+    var numArgs = arguments.length;
+    removeNum = Math.max(removeNum || 0, 0);
+    if (numArgs === 0 || (numArgs === 2 && !removeNum)) {
+      return this;
+    }
+    // If index is negative, it should resolve relative to the size of the
+    // collection. However size may be expensive to compute if not cached, so
+    // only call count() if the number is in fact negative.
+    index = resolveBegin(index, index < 0 ? this.count() : this.size);
+    var spliced = this.slice(0, index);
+    return reify(
+      this,
+      numArgs === 1
+        ? spliced
+        : spliced.concat(arrCopy(arguments, 2), this.slice(index + removeNum))
+    );
+  },
+
+  // ### More collection methods
+
+  findLastIndex: function findLastIndex(predicate, context) {
+    var entry = this.findLastEntry(predicate, context);
+    return entry ? entry[0] : -1;
+  },
+
+  first: function first(notSetValue) {
+    return this.get(0, notSetValue);
+  },
+
+  flatten: function flatten(depth) {
+    return reify(this, flattenFactory(this, depth, false));
+  },
+
+  get: function get(index, notSetValue) {
+    index = wrapIndex(this, index);
+    return index < 0 ||
+      this.size === Infinity ||
+      (this.size !== undefined && index > this.size)
+      ? notSetValue
+      : this.find(function (_, key) { return key === index; }, undefined, notSetValue);
+  },
+
+  has: function has(index) {
+    index = wrapIndex(this, index);
+    return (
+      index >= 0 &&
+      (this.size !== undefined
+        ? this.size === Infinity || index < this.size
+        : this.indexOf(index) !== -1)
+    );
+  },
+
+  interpose: function interpose(separator) {
+    return reify(this, interposeFactory(this, separator));
+  },
+
+  interleave: function interleave(/*...collections*/) {
+    var collections = [this].concat(arrCopy(arguments));
+    var zipped = zipWithFactory(this.toSeq(), IndexedSeq.of, collections);
+    var interleaved = zipped.flatten(true);
+    if (zipped.size) {
+      interleaved.size = zipped.size * collections.length;
+    }
+    return reify(this, interleaved);
+  },
+
+  keySeq: function keySeq() {
+    return Range(0, this.size);
+  },
+
+  last: function last(notSetValue) {
+    return this.get(-1, notSetValue);
+  },
+
+  skipWhile: function skipWhile(predicate, context) {
+    return reify(this, skipWhileFactory(this, predicate, context, false));
+  },
+
+  zip: function zip(/*, ...collections */) {
+    var collections = [this].concat(arrCopy(arguments));
+    return reify(this, zipWithFactory(this, defaultZipper, collections));
+  },
+
+  zipAll: function zipAll(/*, ...collections */) {
+    var collections = [this].concat(arrCopy(arguments));
+    return reify(this, zipWithFactory(this, defaultZipper, collections, true));
+  },
+
+  zipWith: function zipWith(zipper /*, ...collections */) {
+    var collections = arrCopy(arguments);
+    collections[0] = this;
+    return reify(this, zipWithFactory(this, zipper, collections));
+  },
+});
+
+var IndexedCollectionPrototype = IndexedCollection.prototype;
+IndexedCollectionPrototype[IS_INDEXED_SYMBOL] = true;
+IndexedCollectionPrototype[IS_ORDERED_SYMBOL] = true;
+
+mixin(SetCollection, {
+  // ### ES6 Collection methods (ES6 Array and Map)
+
+  get: function get(value, notSetValue) {
+    return this.has(value) ? value : notSetValue;
+  },
+
+  includes: function includes(value) {
+    return this.has(value);
+  },
+
+  // ### More sequential methods
+
+  keySeq: function keySeq() {
+    return this.valueSeq();
+  },
+});
+
+var SetCollectionPrototype = SetCollection.prototype;
+SetCollectionPrototype.has = CollectionPrototype.includes;
+SetCollectionPrototype.contains = SetCollectionPrototype.includes;
+SetCollectionPrototype.keys = SetCollectionPrototype.values;
+
+// Mixin subclasses
+
+mixin(KeyedSeq, KeyedCollectionPrototype);
+mixin(IndexedSeq, IndexedCollectionPrototype);
+mixin(SetSeq, SetCollectionPrototype);
+
+// #pragma Helper functions
+
+function reduce(collection, reducer, reduction, context, useFirst, reverse) {
+  assertNotInfinite(collection.size);
+  collection.__iterate(function (v, k, c) {
+    if (useFirst) {
+      useFirst = false;
+      reduction = v;
+    } else {
+      reduction = reducer.call(context, reduction, v, k, c);
+    }
+  }, reverse);
+  return reduction;
+}
+
+function keyMapper(v, k) {
+  return k;
+}
+
+function entryMapper(v, k) {
+  return [k, v];
+}
+
+function not(predicate) {
+  return function () {
+    return !predicate.apply(this, arguments);
+  };
+}
+
+function neg(predicate) {
+  return function () {
+    return -predicate.apply(this, arguments);
+  };
+}
+
+function defaultZipper() {
+  return arrCopy(arguments);
+}
+
+function defaultNegComparator(a, b) {
+  return a < b ? 1 : a > b ? -1 : 0;
+}
+
+function hashCollection(collection) {
+  if (collection.size === Infinity) {
+    return 0;
+  }
+  var ordered = isOrdered(collection);
+  var keyed = isKeyed(collection);
+  var h = ordered ? 1 : 0;
+
+  collection.__iterate(
+    keyed
+      ? ordered
+        ? function (v, k) {
+            h = (31 * h + hashMerge(hash(v), hash(k))) | 0;
+          }
+        : function (v, k) {
+            h = (h + hashMerge(hash(v), hash(k))) | 0;
+          }
+      : ordered
+      ? function (v) {
+          h = (31 * h + hash(v)) | 0;
+        }
+      : function (v) {
+          h = (h + hash(v)) | 0;
+        }
+  );
+
+  return murmurHashOfSize(collection.size, h);
+}
+
+function murmurHashOfSize(size, h) {
+  h = imul(h, 0xcc9e2d51);
+  h = imul((h << 15) | (h >>> -15), 0x1b873593);
+  h = imul((h << 13) | (h >>> -13), 5);
+  h = ((h + 0xe6546b64) | 0) ^ size;
+  h = imul(h ^ (h >>> 16), 0x85ebca6b);
+  h = imul(h ^ (h >>> 13), 0xc2b2ae35);
+  h = smi(h ^ (h >>> 16));
+  return h;
+}
+
+function hashMerge(a, b) {
+  return (a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2))) | 0; // int
+}
+
+var OrderedSet = /*@__PURE__*/(function (Set) {
+  function OrderedSet(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptyOrderedSet()
+      : isOrderedSet(value)
+      ? value
+      : emptyOrderedSet().withMutations(function (set) {
+          var iter = SetCollection(value);
+          assertNotInfinite(iter.size);
+          iter.forEach(function (v) { return set.add(v); });
+        });
+  }
+
+  if ( Set ) OrderedSet.__proto__ = Set;
+  OrderedSet.prototype = Object.create( Set && Set.prototype );
+  OrderedSet.prototype.constructor = OrderedSet;
+
+  OrderedSet.of = function of (/*...values*/) {
+    return this(arguments);
+  };
+
+  OrderedSet.fromKeys = function fromKeys (value) {
+    return this(KeyedCollection(value).keySeq());
+  };
+
+  OrderedSet.prototype.toString = function toString () {
+    return this.__toString('OrderedSet {', '}');
+  };
+
+  return OrderedSet;
+}(Set));
+
+OrderedSet.isOrderedSet = isOrderedSet;
+
+var OrderedSetPrototype = OrderedSet.prototype;
+OrderedSetPrototype[IS_ORDERED_SYMBOL] = true;
+OrderedSetPrototype.zip = IndexedCollectionPrototype.zip;
+OrderedSetPrototype.zipWith = IndexedCollectionPrototype.zipWith;
+OrderedSetPrototype.zipAll = IndexedCollectionPrototype.zipAll;
+
+OrderedSetPrototype.__empty = emptyOrderedSet;
+OrderedSetPrototype.__make = makeOrderedSet;
+
+function makeOrderedSet(map, ownerID) {
+  var set = Object.create(OrderedSetPrototype);
+  set.size = map ? map.size : 0;
+  set._map = map;
+  set.__ownerID = ownerID;
+  return set;
+}
+
+var EMPTY_ORDERED_SET;
+function emptyOrderedSet() {
+  return (
+    EMPTY_ORDERED_SET || (EMPTY_ORDERED_SET = makeOrderedSet(emptyOrderedMap()))
+  );
+}
+
+var PairSorting = {
+  LeftThenRight: -1,
+  RightThenLeft: +1,
+};
+
+function throwOnInvalidDefaultValues(defaultValues) {
+  if (isRecord(defaultValues)) {
+    throw new Error(
+      'Can not call `Record` with an immutable Record as default values. Use a plain javascript object instead.'
+    );
+  }
+
+  if (isImmutable(defaultValues)) {
+    throw new Error(
+      'Can not call `Record` with an immutable Collection as default values. Use a plain javascript object instead.'
+    );
+  }
+
+  if (defaultValues === null || typeof defaultValues !== 'object') {
+    throw new Error(
+      'Can not call `Record` with a non-object as default values. Use a plain javascript object instead.'
+    );
+  }
+}
+
+var Record = function Record(defaultValues, name) {
+  var hasInitialized;
+
+  throwOnInvalidDefaultValues(defaultValues);
+
+  var RecordType = function Record(values) {
+    var this$1$1 = this;
+
+    if (values instanceof RecordType) {
+      return values;
+    }
+    if (!(this instanceof RecordType)) {
+      return new RecordType(values);
+    }
+    if (!hasInitialized) {
+      hasInitialized = true;
+      var keys = Object.keys(defaultValues);
+      var indices = (RecordTypePrototype._indices = {});
+      // Deprecated: left to attempt not to break any external code which
+      // relies on a ._name property existing on record instances.
+      // Use Record.getDescriptiveName() instead
+      RecordTypePrototype._name = name;
+      RecordTypePrototype._keys = keys;
+      RecordTypePrototype._defaultValues = defaultValues;
+      for (var i = 0; i < keys.length; i++) {
+        var propName = keys[i];
+        indices[propName] = i;
+        if (RecordTypePrototype[propName]) {
+          /* eslint-disable no-console */
+          typeof console === 'object' &&
+            console.warn &&
+            console.warn(
+              'Cannot define ' +
+                recordName(this) +
+                ' with property "' +
+                propName +
+                '" since that property name is part of the Record API.'
+            );
+          /* eslint-enable no-console */
+        } else {
+          setProp(RecordTypePrototype, propName);
+        }
+      }
+    }
+    this.__ownerID = undefined;
+    this._values = List().withMutations(function (l) {
+      l.setSize(this$1$1._keys.length);
+      KeyedCollection(values).forEach(function (v, k) {
+        l.set(this$1$1._indices[k], v === this$1$1._defaultValues[k] ? undefined : v);
+      });
+    });
+    return this;
+  };
+
+  var RecordTypePrototype = (RecordType.prototype =
+    Object.create(RecordPrototype));
+  RecordTypePrototype.constructor = RecordType;
+
+  if (name) {
+    RecordType.displayName = name;
+  }
+
+  // eslint-disable-next-line no-constructor-return
+  return RecordType;
+};
+
+Record.prototype.toString = function toString () {
+  var str = recordName(this) + ' { ';
+  var keys = this._keys;
+  var k;
+  for (var i = 0, l = keys.length; i !== l; i++) {
+    k = keys[i];
+    str += (i ? ', ' : '') + k + ': ' + quoteString(this.get(k));
+  }
+  return str + ' }';
+};
+
+Record.prototype.equals = function equals (other) {
+  return (
+    this === other ||
+    (isRecord(other) && recordSeq(this).equals(recordSeq(other)))
+  );
+};
+
+Record.prototype.hashCode = function hashCode () {
+  return recordSeq(this).hashCode();
+};
+
+// @pragma Access
+
+Record.prototype.has = function has (k) {
+  return this._indices.hasOwnProperty(k);
+};
+
+Record.prototype.get = function get (k, notSetValue) {
+  if (!this.has(k)) {
+    return notSetValue;
+  }
+  var index = this._indices[k];
+  var value = this._values.get(index);
+  return value === undefined ? this._defaultValues[k] : value;
+};
+
+// @pragma Modification
+
+Record.prototype.set = function set (k, v) {
+  if (this.has(k)) {
+    var newValues = this._values.set(
+      this._indices[k],
+      v === this._defaultValues[k] ? undefined : v
+    );
+    if (newValues !== this._values && !this.__ownerID) {
+      return makeRecord(this, newValues);
+    }
+  }
+  return this;
+};
+
+Record.prototype.remove = function remove (k) {
+  return this.set(k);
+};
+
+Record.prototype.clear = function clear () {
+  var newValues = this._values.clear().setSize(this._keys.length);
+
+  return this.__ownerID ? this : makeRecord(this, newValues);
+};
+
+Record.prototype.wasAltered = function wasAltered () {
+  return this._values.wasAltered();
+};
+
+Record.prototype.toSeq = function toSeq () {
+  return recordSeq(this);
+};
+
+Record.prototype.toJS = function toJS$1 () {
+  return toJS(this);
+};
+
+Record.prototype.entries = function entries () {
+  return this.__iterator(ITERATE_ENTRIES);
+};
+
+Record.prototype.__iterator = function __iterator (type, reverse) {
+  return recordSeq(this).__iterator(type, reverse);
+};
+
+Record.prototype.__iterate = function __iterate (fn, reverse) {
+  return recordSeq(this).__iterate(fn, reverse);
+};
+
+Record.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+  if (ownerID === this.__ownerID) {
+    return this;
+  }
+  var newValues = this._values.__ensureOwner(ownerID);
+  if (!ownerID) {
+    this.__ownerID = ownerID;
+    this._values = newValues;
+    return this;
+  }
+  return makeRecord(this, newValues, ownerID);
+};
+
+Record.isRecord = isRecord;
+Record.getDescriptiveName = recordName;
+var RecordPrototype = Record.prototype;
+RecordPrototype[IS_RECORD_SYMBOL] = true;
+RecordPrototype[DELETE] = RecordPrototype.remove;
+RecordPrototype.deleteIn = RecordPrototype.removeIn = deleteIn;
+RecordPrototype.getIn = getIn;
+RecordPrototype.hasIn = CollectionPrototype.hasIn;
+RecordPrototype.merge = merge$1;
+RecordPrototype.mergeWith = mergeWith$1;
+RecordPrototype.mergeIn = mergeIn;
+RecordPrototype.mergeDeep = mergeDeep;
+RecordPrototype.mergeDeepWith = mergeDeepWith;
+RecordPrototype.mergeDeepIn = mergeDeepIn;
+RecordPrototype.setIn = setIn;
+RecordPrototype.update = update;
+RecordPrototype.updateIn = updateIn;
+RecordPrototype.withMutations = withMutations;
+RecordPrototype.asMutable = asMutable;
+RecordPrototype.asImmutable = asImmutable;
+RecordPrototype[ITERATOR_SYMBOL] = RecordPrototype.entries;
+RecordPrototype.toJSON = RecordPrototype.toObject =
+  CollectionPrototype.toObject;
+RecordPrototype.inspect = RecordPrototype.toSource = function () {
+  return this.toString();
+};
+
+function makeRecord(likeRecord, values, ownerID) {
+  var record = Object.create(Object.getPrototypeOf(likeRecord));
+  record._values = values;
+  record.__ownerID = ownerID;
+  return record;
+}
+
+function recordName(record) {
+  return record.constructor.displayName || record.constructor.name || 'Record';
+}
+
+function recordSeq(record) {
+  return keyedSeqFromValue(record._keys.map(function (k) { return [k, record.get(k)]; }));
+}
+
+function setProp(prototype, name) {
+  try {
+    Object.defineProperty(prototype, name, {
+      get: function () {
+        return this.get(name);
+      },
+      set: function (value) {
+        invariant(this.__ownerID, 'Cannot set on an immutable record.');
+        this.set(name, value);
+      },
+    });
+  } catch (error) {
+    // Object.defineProperty failed. Probably IE8.
+  }
+}
+
+/**
+ * Returns a lazy Seq of `value` repeated `times` times. When `times` is
+ * undefined, returns an infinite sequence of `value`.
+ */
+var Repeat = /*@__PURE__*/(function (IndexedSeq) {
+  function Repeat(value, times) {
+    if (!(this instanceof Repeat)) {
+      // eslint-disable-next-line no-constructor-return
+      return new Repeat(value, times);
+    }
+    this._value = value;
+    this.size = times === undefined ? Infinity : Math.max(0, times);
+    if (this.size === 0) {
+      if (EMPTY_REPEAT) {
+        // eslint-disable-next-line no-constructor-return
+        return EMPTY_REPEAT;
+      }
+      // eslint-disable-next-line @typescript-eslint/no-this-alias
+      EMPTY_REPEAT = this;
+    }
+  }
+
+  if ( IndexedSeq ) Repeat.__proto__ = IndexedSeq;
+  Repeat.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+  Repeat.prototype.constructor = Repeat;
+
+  Repeat.prototype.toString = function toString () {
+    if (this.size === 0) {
+      return 'Repeat []';
+    }
+    return 'Repeat [ ' + this._value + ' ' + this.size + ' times ]';
+  };
+
+  Repeat.prototype.get = function get (index, notSetValue) {
+    return this.has(index) ? this._value : notSetValue;
+  };
+
+  Repeat.prototype.includes = function includes (searchValue) {
+    return is(this._value, searchValue);
+  };
+
+  Repeat.prototype.slice = function slice (begin, end) {
+    var size = this.size;
+    return wholeSlice(begin, end, size)
+      ? this
+      : new Repeat(
+          this._value,
+          resolveEnd(end, size) - resolveBegin(begin, size)
+        );
+  };
+
+  Repeat.prototype.reverse = function reverse () {
+    return this;
+  };
+
+  Repeat.prototype.indexOf = function indexOf (searchValue) {
+    if (is(this._value, searchValue)) {
+      return 0;
+    }
+    return -1;
+  };
+
+  Repeat.prototype.lastIndexOf = function lastIndexOf (searchValue) {
+    if (is(this._value, searchValue)) {
+      return this.size;
+    }
+    return -1;
+  };
+
+  Repeat.prototype.__iterate = function __iterate (fn, reverse) {
+    var size = this.size;
+    var i = 0;
+    while (i !== size) {
+      if (fn(this._value, reverse ? size - ++i : i++, this) === false) {
+        break;
+      }
+    }
+    return i;
+  };
+
+  Repeat.prototype.__iterator = function __iterator (type, reverse) {
+    var this$1$1 = this;
+
+    var size = this.size;
+    var i = 0;
+    return new Iterator(function () { return i === size
+        ? iteratorDone()
+        : iteratorValue(type, reverse ? size - ++i : i++, this$1$1._value); }
+    );
+  };
+
+  Repeat.prototype.equals = function equals (other) {
+    return other instanceof Repeat
+      ? is(this._value, other._value)
+      : deepEqual(this, other);
+  };
+
+  return Repeat;
+}(IndexedSeq));
+
+var EMPTY_REPEAT;
+
+function fromJS(value, converter) {
+  return fromJSWith(
+    [],
+    converter || defaultConverter,
+    value,
+    '',
+    converter && converter.length > 2 ? [] : undefined,
+    { '': value }
+  );
+}
+
+function fromJSWith(stack, converter, value, key, keyPath, parentValue) {
+  if (
+    typeof value !== 'string' &&
+    !isImmutable(value) &&
+    (isArrayLike(value) || hasIterator(value) || isPlainObject(value))
+  ) {
+    if (~stack.indexOf(value)) {
+      throw new TypeError('Cannot convert circular structure to Immutable');
+    }
+    stack.push(value);
+    keyPath && key !== '' && keyPath.push(key);
+    var converted = converter.call(
+      parentValue,
+      key,
+      Seq(value).map(function (v, k) { return fromJSWith(stack, converter, v, k, keyPath, value); }
+      ),
+      keyPath && keyPath.slice()
+    );
+    stack.pop();
+    keyPath && keyPath.pop();
+    return converted;
+  }
+  return value;
+}
+
+function defaultConverter(k, v) {
+  // Effectively the opposite of "Collection.toSeq()"
+  return isIndexed(v) ? v.toList() : isKeyed(v) ? v.toMap() : v.toSet();
+}
+
+var version = "5.0.3";
+
+// Note: Iterable is deprecated
+var Iterable = Collection;
+
+export { Collection, Iterable, List, Map, OrderedMap, OrderedSet, PairSorting, Range, Record, Repeat, Seq, Set, Stack, fromJS, get, getIn$1 as getIn, has, hasIn$1 as hasIn, hash, is, isAssociative, isCollection, isImmutable, isIndexed, isKeyed, isList, isMap, isOrdered, isOrderedMap, isOrderedSet, isPlainObject, isRecord, isSeq, isSet, isStack, isValueObject, merge, mergeDeep$1 as mergeDeep, mergeDeepWith$1 as mergeDeepWith, mergeWith, remove, removeIn, set, setIn$1 as setIn, update$1 as update, updateIn$1 as updateIn, version };
Index: imaps-frontend/node_modules/immutable/dist/immutable.js
===================================================================
--- imaps-frontend/node_modules/immutable/dist/immutable.js	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
+++ imaps-frontend/node_modules/immutable/dist/immutable.js	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
@@ -0,0 +1,5990 @@
+/**
+ * @license
+ * MIT License
+ * 
+ * Copyright (c) 2014-present, Lee Byron and other contributors.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+(function (global, factory) {
+  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+  typeof define === 'function' && define.amd ? define(['exports'], factory) :
+  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Immutable = {}));
+})(this, (function (exports) { 'use strict';
+
+  // Used for setting prototype methods that IE8 chokes on.
+  var DELETE = 'delete';
+
+  // Constants describing the size of trie nodes.
+  var SHIFT = 5; // Resulted in best performance after ______?
+  var SIZE = 1 << SHIFT;
+  var MASK = SIZE - 1;
+
+  // A consistent shared value representing "not set" which equals nothing other
+  // than itself, and nothing that could be provided externally.
+  var NOT_SET = {};
+
+  // Boolean references, Rough equivalent of `bool &`.
+  function MakeRef() {
+    return { value: false };
+  }
+
+  function SetRef(ref) {
+    if (ref) {
+      ref.value = true;
+    }
+  }
+
+  // A function which returns a value representing an "owner" for transient writes
+  // to tries. The return value will only ever equal itself, and will not equal
+  // the return of any subsequent call of this function.
+  function OwnerID() {}
+
+  function ensureSize(iter) {
+    if (iter.size === undefined) {
+      iter.size = iter.__iterate(returnTrue);
+    }
+    return iter.size;
+  }
+
+  function wrapIndex(iter, index) {
+    // This implements "is array index" which the ECMAString spec defines as:
+    //
+    //     A String property name P is an array index if and only if
+    //     ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal
+    //     to 2^32−1.
+    //
+    // http://www.ecma-international.org/ecma-262/6.0/#sec-array-exotic-objects
+    if (typeof index !== 'number') {
+      var uint32Index = index >>> 0; // N >>> 0 is shorthand for ToUint32
+      if ('' + uint32Index !== index || uint32Index === 4294967295) {
+        return NaN;
+      }
+      index = uint32Index;
+    }
+    return index < 0 ? ensureSize(iter) + index : index;
+  }
+
+  function returnTrue() {
+    return true;
+  }
+
+  function wholeSlice(begin, end, size) {
+    return (
+      ((begin === 0 && !isNeg(begin)) ||
+        (size !== undefined && begin <= -size)) &&
+      (end === undefined || (size !== undefined && end >= size))
+    );
+  }
+
+  function resolveBegin(begin, size) {
+    return resolveIndex(begin, size, 0);
+  }
+
+  function resolveEnd(end, size) {
+    return resolveIndex(end, size, size);
+  }
+
+  function resolveIndex(index, size, defaultIndex) {
+    // Sanitize indices using this shorthand for ToInt32(argument)
+    // http://www.ecma-international.org/ecma-262/6.0/#sec-toint32
+    return index === undefined
+      ? defaultIndex
+      : isNeg(index)
+      ? size === Infinity
+        ? size
+        : Math.max(0, size + index) | 0
+      : size === undefined || size === index
+      ? index
+      : Math.min(size, index) | 0;
+  }
+
+  function isNeg(value) {
+    // Account for -0 which is negative, but not less than 0.
+    return value < 0 || (value === 0 && 1 / value === -Infinity);
+  }
+
+  // Note: value is unchanged to not break immutable-devtools.
+  var IS_COLLECTION_SYMBOL = '@@__IMMUTABLE_ITERABLE__@@';
+
+  function isCollection(maybeCollection) {
+    return Boolean(maybeCollection && maybeCollection[IS_COLLECTION_SYMBOL]);
+  }
+
+  var IS_KEYED_SYMBOL = '@@__IMMUTABLE_KEYED__@@';
+
+  function isKeyed(maybeKeyed) {
+    return Boolean(maybeKeyed && maybeKeyed[IS_KEYED_SYMBOL]);
+  }
+
+  var IS_INDEXED_SYMBOL = '@@__IMMUTABLE_INDEXED__@@';
+
+  function isIndexed(maybeIndexed) {
+    return Boolean(maybeIndexed && maybeIndexed[IS_INDEXED_SYMBOL]);
+  }
+
+  function isAssociative(maybeAssociative) {
+    return isKeyed(maybeAssociative) || isIndexed(maybeAssociative);
+  }
+
+  var Collection = function Collection(value) {
+    // eslint-disable-next-line no-constructor-return
+    return isCollection(value) ? value : Seq(value);
+  };
+
+  var KeyedCollection = /*@__PURE__*/(function (Collection) {
+    function KeyedCollection(value) {
+      // eslint-disable-next-line no-constructor-return
+      return isKeyed(value) ? value : KeyedSeq(value);
+    }
+
+    if ( Collection ) KeyedCollection.__proto__ = Collection;
+    KeyedCollection.prototype = Object.create( Collection && Collection.prototype );
+    KeyedCollection.prototype.constructor = KeyedCollection;
+
+    return KeyedCollection;
+  }(Collection));
+
+  var IndexedCollection = /*@__PURE__*/(function (Collection) {
+    function IndexedCollection(value) {
+      // eslint-disable-next-line no-constructor-return
+      return isIndexed(value) ? value : IndexedSeq(value);
+    }
+
+    if ( Collection ) IndexedCollection.__proto__ = Collection;
+    IndexedCollection.prototype = Object.create( Collection && Collection.prototype );
+    IndexedCollection.prototype.constructor = IndexedCollection;
+
+    return IndexedCollection;
+  }(Collection));
+
+  var SetCollection = /*@__PURE__*/(function (Collection) {
+    function SetCollection(value) {
+      // eslint-disable-next-line no-constructor-return
+      return isCollection(value) && !isAssociative(value) ? value : SetSeq(value);
+    }
+
+    if ( Collection ) SetCollection.__proto__ = Collection;
+    SetCollection.prototype = Object.create( Collection && Collection.prototype );
+    SetCollection.prototype.constructor = SetCollection;
+
+    return SetCollection;
+  }(Collection));
+
+  Collection.Keyed = KeyedCollection;
+  Collection.Indexed = IndexedCollection;
+  Collection.Set = SetCollection;
+
+  var IS_SEQ_SYMBOL = '@@__IMMUTABLE_SEQ__@@';
+
+  function isSeq(maybeSeq) {
+    return Boolean(maybeSeq && maybeSeq[IS_SEQ_SYMBOL]);
+  }
+
+  var IS_RECORD_SYMBOL = '@@__IMMUTABLE_RECORD__@@';
+
+  function isRecord(maybeRecord) {
+    return Boolean(maybeRecord && maybeRecord[IS_RECORD_SYMBOL]);
+  }
+
+  function isImmutable(maybeImmutable) {
+    return isCollection(maybeImmutable) || isRecord(maybeImmutable);
+  }
+
+  var IS_ORDERED_SYMBOL = '@@__IMMUTABLE_ORDERED__@@';
+
+  function isOrdered(maybeOrdered) {
+    return Boolean(maybeOrdered && maybeOrdered[IS_ORDERED_SYMBOL]);
+  }
+
+  var ITERATE_KEYS = 0;
+  var ITERATE_VALUES = 1;
+  var ITERATE_ENTRIES = 2;
+
+  var REAL_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
+  var FAUX_ITERATOR_SYMBOL = '@@iterator';
+
+  var ITERATOR_SYMBOL = REAL_ITERATOR_SYMBOL || FAUX_ITERATOR_SYMBOL;
+
+  var Iterator = function Iterator(next) {
+    this.next = next;
+  };
+
+  Iterator.prototype.toString = function toString () {
+    return '[Iterator]';
+  };
+
+  Iterator.KEYS = ITERATE_KEYS;
+  Iterator.VALUES = ITERATE_VALUES;
+  Iterator.ENTRIES = ITERATE_ENTRIES;
+
+  Iterator.prototype.inspect = Iterator.prototype.toSource = function () {
+    return this.toString();
+  };
+  Iterator.prototype[ITERATOR_SYMBOL] = function () {
+    return this;
+  };
+
+  function iteratorValue(type, k, v, iteratorResult) {
+    var value = type === 0 ? k : type === 1 ? v : [k, v];
+    iteratorResult
+      ? (iteratorResult.value = value)
+      : (iteratorResult = {
+          value: value,
+          done: false,
+        });
+    return iteratorResult;
+  }
+
+  function iteratorDone() {
+    return { value: undefined, done: true };
+  }
+
+  function hasIterator(maybeIterable) {
+    if (Array.isArray(maybeIterable)) {
+      // IE11 trick as it does not support `Symbol.iterator`
+      return true;
+    }
+
+    return !!getIteratorFn(maybeIterable);
+  }
+
+  function isIterator(maybeIterator) {
+    return maybeIterator && typeof maybeIterator.next === 'function';
+  }
+
+  function getIterator(iterable) {
+    var iteratorFn = getIteratorFn(iterable);
+    return iteratorFn && iteratorFn.call(iterable);
+  }
+
+  function getIteratorFn(iterable) {
+    var iteratorFn =
+      iterable &&
+      ((REAL_ITERATOR_SYMBOL && iterable[REAL_ITERATOR_SYMBOL]) ||
+        iterable[FAUX_ITERATOR_SYMBOL]);
+    if (typeof iteratorFn === 'function') {
+      return iteratorFn;
+    }
+  }
+
+  function isEntriesIterable(maybeIterable) {
+    var iteratorFn = getIteratorFn(maybeIterable);
+    return iteratorFn && iteratorFn === maybeIterable.entries;
+  }
+
+  function isKeysIterable(maybeIterable) {
+    var iteratorFn = getIteratorFn(maybeIterable);
+    return iteratorFn && iteratorFn === maybeIterable.keys;
+  }
+
+  var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+  function isArrayLike(value) {
+    if (Array.isArray(value) || typeof value === 'string') {
+      return true;
+    }
+
+    return (
+      value &&
+      typeof value === 'object' &&
+      Number.isInteger(value.length) &&
+      value.length >= 0 &&
+      (value.length === 0
+        ? // Only {length: 0} is considered Array-like.
+          Object.keys(value).length === 1
+        : // An object is only Array-like if it has a property where the last value
+          // in the array-like may be found (which could be undefined).
+          value.hasOwnProperty(value.length - 1))
+    );
+  }
+
+  var Seq = /*@__PURE__*/(function (Collection) {
+    function Seq(value) {
+      // eslint-disable-next-line no-constructor-return
+      return value === undefined || value === null
+        ? emptySequence()
+        : isImmutable(value)
+        ? value.toSeq()
+        : seqFromValue(value);
+    }
+
+    if ( Collection ) Seq.__proto__ = Collection;
+    Seq.prototype = Object.create( Collection && Collection.prototype );
+    Seq.prototype.constructor = Seq;
+
+    Seq.prototype.toSeq = function toSeq () {
+      return this;
+    };
+
+    Seq.prototype.toString = function toString () {
+      return this.__toString('Seq {', '}');
+    };
+
+    Seq.prototype.cacheResult = function cacheResult () {
+      if (!this._cache && this.__iterateUncached) {
+        this._cache = this.entrySeq().toArray();
+        this.size = this._cache.length;
+      }
+      return this;
+    };
+
+    // abstract __iterateUncached(fn, reverse)
+
+    Seq.prototype.__iterate = function __iterate (fn, reverse) {
+      var cache = this._cache;
+      if (cache) {
+        var size = cache.length;
+        var i = 0;
+        while (i !== size) {
+          var entry = cache[reverse ? size - ++i : i++];
+          if (fn(entry[1], entry[0], this) === false) {
+            break;
+          }
+        }
+        return i;
+      }
+      return this.__iterateUncached(fn, reverse);
+    };
+
+    // abstract __iteratorUncached(type, reverse)
+
+    Seq.prototype.__iterator = function __iterator (type, reverse) {
+      var cache = this._cache;
+      if (cache) {
+        var size = cache.length;
+        var i = 0;
+        return new Iterator(function () {
+          if (i === size) {
+            return iteratorDone();
+          }
+          var entry = cache[reverse ? size - ++i : i++];
+          return iteratorValue(type, entry[0], entry[1]);
+        });
+      }
+      return this.__iteratorUncached(type, reverse);
+    };
+
+    return Seq;
+  }(Collection));
+
+  var KeyedSeq = /*@__PURE__*/(function (Seq) {
+    function KeyedSeq(value) {
+      // eslint-disable-next-line no-constructor-return
+      return value === undefined || value === null
+        ? emptySequence().toKeyedSeq()
+        : isCollection(value)
+        ? isKeyed(value)
+          ? value.toSeq()
+          : value.fromEntrySeq()
+        : isRecord(value)
+        ? value.toSeq()
+        : keyedSeqFromValue(value);
+    }
+
+    if ( Seq ) KeyedSeq.__proto__ = Seq;
+    KeyedSeq.prototype = Object.create( Seq && Seq.prototype );
+    KeyedSeq.prototype.constructor = KeyedSeq;
+
+    KeyedSeq.prototype.toKeyedSeq = function toKeyedSeq () {
+      return this;
+    };
+
+    return KeyedSeq;
+  }(Seq));
+
+  var IndexedSeq = /*@__PURE__*/(function (Seq) {
+    function IndexedSeq(value) {
+      // eslint-disable-next-line no-constructor-return
+      return value === undefined || value === null
+        ? emptySequence()
+        : isCollection(value)
+        ? isKeyed(value)
+          ? value.entrySeq()
+          : value.toIndexedSeq()
+        : isRecord(value)
+        ? value.toSeq().entrySeq()
+        : indexedSeqFromValue(value);
+    }
+
+    if ( Seq ) IndexedSeq.__proto__ = Seq;
+    IndexedSeq.prototype = Object.create( Seq && Seq.prototype );
+    IndexedSeq.prototype.constructor = IndexedSeq;
+
+    IndexedSeq.of = function of (/*...values*/) {
+      return IndexedSeq(arguments);
+    };
+
+    IndexedSeq.prototype.toIndexedSeq = function toIndexedSeq () {
+      return this;
+    };
+
+    IndexedSeq.prototype.toString = function toString () {
+      return this.__toString('Seq [', ']');
+    };
+
+    return IndexedSeq;
+  }(Seq));
+
+  var SetSeq = /*@__PURE__*/(function (Seq) {
+    function SetSeq(value) {
+      // eslint-disable-next-line no-constructor-return
+      return (
+        isCollection(value) && !isAssociative(value) ? value : IndexedSeq(value)
+      ).toSetSeq();
+    }
+
+    if ( Seq ) SetSeq.__proto__ = Seq;
+    SetSeq.prototype = Object.create( Seq && Seq.prototype );
+    SetSeq.prototype.constructor = SetSeq;
+
+    SetSeq.of = function of (/*...values*/) {
+      return SetSeq(arguments);
+    };
+
+    SetSeq.prototype.toSetSeq = function toSetSeq () {
+      return this;
+    };
+
+    return SetSeq;
+  }(Seq));
+
+  Seq.isSeq = isSeq;
+  Seq.Keyed = KeyedSeq;
+  Seq.Set = SetSeq;
+  Seq.Indexed = IndexedSeq;
+
+  Seq.prototype[IS_SEQ_SYMBOL] = true;
+
+  // #pragma Root Sequences
+
+  var ArraySeq = /*@__PURE__*/(function (IndexedSeq) {
+    function ArraySeq(array) {
+      this._array = array;
+      this.size = array.length;
+    }
+
+    if ( IndexedSeq ) ArraySeq.__proto__ = IndexedSeq;
+    ArraySeq.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+    ArraySeq.prototype.constructor = ArraySeq;
+
+    ArraySeq.prototype.get = function get (index, notSetValue) {
+      return this.has(index) ? this._array[wrapIndex(this, index)] : notSetValue;
+    };
+
+    ArraySeq.prototype.__iterate = function __iterate (fn, reverse) {
+      var array = this._array;
+      var size = array.length;
+      var i = 0;
+      while (i !== size) {
+        var ii = reverse ? size - ++i : i++;
+        if (fn(array[ii], ii, this) === false) {
+          break;
+        }
+      }
+      return i;
+    };
+
+    ArraySeq.prototype.__iterator = function __iterator (type, reverse) {
+      var array = this._array;
+      var size = array.length;
+      var i = 0;
+      return new Iterator(function () {
+        if (i === size) {
+          return iteratorDone();
+        }
+        var ii = reverse ? size - ++i : i++;
+        return iteratorValue(type, ii, array[ii]);
+      });
+    };
+
+    return ArraySeq;
+  }(IndexedSeq));
+
+  var ObjectSeq = /*@__PURE__*/(function (KeyedSeq) {
+    function ObjectSeq(object) {
+      var keys = Object.keys(object).concat(
+        Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols(object) : []
+      );
+      this._object = object;
+      this._keys = keys;
+      this.size = keys.length;
+    }
+
+    if ( KeyedSeq ) ObjectSeq.__proto__ = KeyedSeq;
+    ObjectSeq.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
+    ObjectSeq.prototype.constructor = ObjectSeq;
+
+    ObjectSeq.prototype.get = function get (key, notSetValue) {
+      if (notSetValue !== undefined && !this.has(key)) {
+        return notSetValue;
+      }
+      return this._object[key];
+    };
+
+    ObjectSeq.prototype.has = function has (key) {
+      return hasOwnProperty.call(this._object, key);
+    };
+
+    ObjectSeq.prototype.__iterate = function __iterate (fn, reverse) {
+      var object = this._object;
+      var keys = this._keys;
+      var size = keys.length;
+      var i = 0;
+      while (i !== size) {
+        var key = keys[reverse ? size - ++i : i++];
+        if (fn(object[key], key, this) === false) {
+          break;
+        }
+      }
+      return i;
+    };
+
+    ObjectSeq.prototype.__iterator = function __iterator (type, reverse) {
+      var object = this._object;
+      var keys = this._keys;
+      var size = keys.length;
+      var i = 0;
+      return new Iterator(function () {
+        if (i === size) {
+          return iteratorDone();
+        }
+        var key = keys[reverse ? size - ++i : i++];
+        return iteratorValue(type, key, object[key]);
+      });
+    };
+
+    return ObjectSeq;
+  }(KeyedSeq));
+  ObjectSeq.prototype[IS_ORDERED_SYMBOL] = true;
+
+  var CollectionSeq = /*@__PURE__*/(function (IndexedSeq) {
+    function CollectionSeq(collection) {
+      this._collection = collection;
+      this.size = collection.length || collection.size;
+    }
+
+    if ( IndexedSeq ) CollectionSeq.__proto__ = IndexedSeq;
+    CollectionSeq.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+    CollectionSeq.prototype.constructor = CollectionSeq;
+
+    CollectionSeq.prototype.__iterateUncached = function __iterateUncached (fn, reverse) {
+      if (reverse) {
+        return this.cacheResult().__iterate(fn, reverse);
+      }
+      var collection = this._collection;
+      var iterator = getIterator(collection);
+      var iterations = 0;
+      if (isIterator(iterator)) {
+        var step;
+        while (!(step = iterator.next()).done) {
+          if (fn(step.value, iterations++, this) === false) {
+            break;
+          }
+        }
+      }
+      return iterations;
+    };
+
+    CollectionSeq.prototype.__iteratorUncached = function __iteratorUncached (type, reverse) {
+      if (reverse) {
+        return this.cacheResult().__iterator(type, reverse);
+      }
+      var collection = this._collection;
+      var iterator = getIterator(collection);
+      if (!isIterator(iterator)) {
+        return new Iterator(iteratorDone);
+      }
+      var iterations = 0;
+      return new Iterator(function () {
+        var step = iterator.next();
+        return step.done ? step : iteratorValue(type, iterations++, step.value);
+      });
+    };
+
+    return CollectionSeq;
+  }(IndexedSeq));
+
+  // # pragma Helper functions
+
+  var EMPTY_SEQ;
+
+  function emptySequence() {
+    return EMPTY_SEQ || (EMPTY_SEQ = new ArraySeq([]));
+  }
+
+  function keyedSeqFromValue(value) {
+    var seq = maybeIndexedSeqFromValue(value);
+    if (seq) {
+      return seq.fromEntrySeq();
+    }
+    if (typeof value === 'object') {
+      return new ObjectSeq(value);
+    }
+    throw new TypeError(
+      'Expected Array or collection object of [k, v] entries, or keyed object: ' +
+        value
+    );
+  }
+
+  function indexedSeqFromValue(value) {
+    var seq = maybeIndexedSeqFromValue(value);
+    if (seq) {
+      return seq;
+    }
+    throw new TypeError(
+      'Expected Array or collection object of values: ' + value
+    );
+  }
+
+  function seqFromValue(value) {
+    var seq = maybeIndexedSeqFromValue(value);
+    if (seq) {
+      return isEntriesIterable(value)
+        ? seq.fromEntrySeq()
+        : isKeysIterable(value)
+        ? seq.toSetSeq()
+        : seq;
+    }
+    if (typeof value === 'object') {
+      return new ObjectSeq(value);
+    }
+    throw new TypeError(
+      'Expected Array or collection object of values, or keyed object: ' + value
+    );
+  }
+
+  function maybeIndexedSeqFromValue(value) {
+    return isArrayLike(value)
+      ? new ArraySeq(value)
+      : hasIterator(value)
+      ? new CollectionSeq(value)
+      : undefined;
+  }
+
+  var IS_MAP_SYMBOL = '@@__IMMUTABLE_MAP__@@';
+
+  function isMap(maybeMap) {
+    return Boolean(maybeMap && maybeMap[IS_MAP_SYMBOL]);
+  }
+
+  function isOrderedMap(maybeOrderedMap) {
+    return isMap(maybeOrderedMap) && isOrdered(maybeOrderedMap);
+  }
+
+  function isValueObject(maybeValue) {
+    return Boolean(
+      maybeValue &&
+        typeof maybeValue.equals === 'function' &&
+        typeof maybeValue.hashCode === 'function'
+    );
+  }
+
+  /**
+   * An extension of the "same-value" algorithm as [described for use by ES6 Map
+   * and Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality)
+   *
+   * NaN is considered the same as NaN, however -0 and 0 are considered the same
+   * value, which is different from the algorithm described by
+   * [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is).
+   *
+   * This is extended further to allow Objects to describe the values they
+   * represent, by way of `valueOf` or `equals` (and `hashCode`).
+   *
+   * Note: because of this extension, the key equality of Immutable.Map and the
+   * value equality of Immutable.Set will differ from ES6 Map and Set.
+   *
+   * ### Defining custom values
+   *
+   * The easiest way to describe the value an object represents is by implementing
+   * `valueOf`. For example, `Date` represents a value by returning a unix
+   * timestamp for `valueOf`:
+   *
+   *     var date1 = new Date(1234567890000); // Fri Feb 13 2009 ...
+   *     var date2 = new Date(1234567890000);
+   *     date1.valueOf(); // 1234567890000
+   *     assert( date1 !== date2 );
+   *     assert( Immutable.is( date1, date2 ) );
+   *
+   * Note: overriding `valueOf` may have other implications if you use this object
+   * where JavaScript expects a primitive, such as implicit string coercion.
+   *
+   * For more complex types, especially collections, implementing `valueOf` may
+   * not be performant. An alternative is to implement `equals` and `hashCode`.
+   *
+   * `equals` takes another object, presumably of similar type, and returns true
+   * if it is equal. Equality is symmetrical, so the same result should be
+   * returned if this and the argument are flipped.
+   *
+   *     assert( a.equals(b) === b.equals(a) );
+   *
+   * `hashCode` returns a 32bit integer number representing the object which will
+   * be used to determine how to store the value object in a Map or Set. You must
+   * provide both or neither methods, one must not exist without the other.
+   *
+   * Also, an important relationship between these methods must be upheld: if two
+   * values are equal, they *must* return the same hashCode. If the values are not
+   * equal, they might have the same hashCode; this is called a hash collision,
+   * and while undesirable for performance reasons, it is acceptable.
+   *
+   *     if (a.equals(b)) {
+   *       assert( a.hashCode() === b.hashCode() );
+   *     }
+   *
+   * All Immutable collections are Value Objects: they implement `equals()`
+   * and `hashCode()`.
+   */
+  function is(valueA, valueB) {
+    if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {
+      return true;
+    }
+    if (!valueA || !valueB) {
+      return false;
+    }
+    if (
+      typeof valueA.valueOf === 'function' &&
+      typeof valueB.valueOf === 'function'
+    ) {
+      valueA = valueA.valueOf();
+      valueB = valueB.valueOf();
+      if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {
+        return true;
+      }
+      if (!valueA || !valueB) {
+        return false;
+      }
+    }
+    return !!(
+      isValueObject(valueA) &&
+      isValueObject(valueB) &&
+      valueA.equals(valueB)
+    );
+  }
+
+  var imul =
+    typeof Math.imul === 'function' && Math.imul(0xffffffff, 2) === -2
+      ? Math.imul
+      : function imul(a, b) {
+          a |= 0; // int
+          b |= 0; // int
+          var c = a & 0xffff;
+          var d = b & 0xffff;
+          // Shift by 0 fixes the sign on the high part.
+          return (c * d + ((((a >>> 16) * d + c * (b >>> 16)) << 16) >>> 0)) | 0; // int
+        };
+
+  // v8 has an optimization for storing 31-bit signed numbers.
+  // Values which have either 00 or 11 as the high order bits qualify.
+  // This function drops the highest order bit in a signed number, maintaining
+  // the sign bit.
+  function smi(i32) {
+    return ((i32 >>> 1) & 0x40000000) | (i32 & 0xbfffffff);
+  }
+
+  var defaultValueOf = Object.prototype.valueOf;
+
+  function hash(o) {
+    if (o == null) {
+      return hashNullish(o);
+    }
+
+    if (typeof o.hashCode === 'function') {
+      // Drop any high bits from accidentally long hash codes.
+      return smi(o.hashCode(o));
+    }
+
+    var v = valueOf(o);
+
+    if (v == null) {
+      return hashNullish(v);
+    }
+
+    switch (typeof v) {
+      case 'boolean':
+        // The hash values for built-in constants are a 1 value for each 5-byte
+        // shift region expect for the first, which encodes the value. This
+        // reduces the odds of a hash collision for these common values.
+        return v ? 0x42108421 : 0x42108420;
+      case 'number':
+        return hashNumber(v);
+      case 'string':
+        return v.length > STRING_HASH_CACHE_MIN_STRLEN
+          ? cachedHashString(v)
+          : hashString(v);
+      case 'object':
+      case 'function':
+        return hashJSObj(v);
+      case 'symbol':
+        return hashSymbol(v);
+      default:
+        if (typeof v.toString === 'function') {
+          return hashString(v.toString());
+        }
+        throw new Error('Value type ' + typeof v + ' cannot be hashed.');
+    }
+  }
+
+  function hashNullish(nullish) {
+    return nullish === null ? 0x42108422 : /* undefined */ 0x42108423;
+  }
+
+  // Compress arbitrarily large numbers into smi hashes.
+  function hashNumber(n) {
+    if (n !== n || n === Infinity) {
+      return 0;
+    }
+    var hash = n | 0;
+    if (hash !== n) {
+      hash ^= n * 0xffffffff;
+    }
+    while (n > 0xffffffff) {
+      n /= 0xffffffff;
+      hash ^= n;
+    }
+    return smi(hash);
+  }
+
+  function cachedHashString(string) {
+    var hashed = stringHashCache[string];
+    if (hashed === undefined) {
+      hashed = hashString(string);
+      if (STRING_HASH_CACHE_SIZE === STRING_HASH_CACHE_MAX_SIZE) {
+        STRING_HASH_CACHE_SIZE = 0;
+        stringHashCache = {};
+      }
+      STRING_HASH_CACHE_SIZE++;
+      stringHashCache[string] = hashed;
+    }
+    return hashed;
+  }
+
+  // http://jsperf.com/hashing-strings
+  function hashString(string) {
+    // This is the hash from JVM
+    // The hash code for a string is computed as
+    // s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1],
+    // where s[i] is the ith character of the string and n is the length of
+    // the string. We "mod" the result to make it between 0 (inclusive) and 2^31
+    // (exclusive) by dropping high bits.
+    var hashed = 0;
+    for (var ii = 0; ii < string.length; ii++) {
+      hashed = (31 * hashed + string.charCodeAt(ii)) | 0;
+    }
+    return smi(hashed);
+  }
+
+  function hashSymbol(sym) {
+    var hashed = symbolMap[sym];
+    if (hashed !== undefined) {
+      return hashed;
+    }
+
+    hashed = nextHash();
+
+    symbolMap[sym] = hashed;
+
+    return hashed;
+  }
+
+  function hashJSObj(obj) {
+    var hashed;
+    if (usingWeakMap) {
+      hashed = weakMap.get(obj);
+      if (hashed !== undefined) {
+        return hashed;
+      }
+    }
+
+    hashed = obj[UID_HASH_KEY];
+    if (hashed !== undefined) {
+      return hashed;
+    }
+
+    if (!canDefineProperty) {
+      hashed = obj.propertyIsEnumerable && obj.propertyIsEnumerable[UID_HASH_KEY];
+      if (hashed !== undefined) {
+        return hashed;
+      }
+
+      hashed = getIENodeHash(obj);
+      if (hashed !== undefined) {
+        return hashed;
+      }
+    }
+
+    hashed = nextHash();
+
+    if (usingWeakMap) {
+      weakMap.set(obj, hashed);
+    } else if (isExtensible !== undefined && isExtensible(obj) === false) {
+      throw new Error('Non-extensible objects are not allowed as keys.');
+    } else if (canDefineProperty) {
+      Object.defineProperty(obj, UID_HASH_KEY, {
+        enumerable: false,
+        configurable: false,
+        writable: false,
+        value: hashed,
+      });
+    } else if (
+      obj.propertyIsEnumerable !== undefined &&
+      obj.propertyIsEnumerable === obj.constructor.prototype.propertyIsEnumerable
+    ) {
+      // Since we can't define a non-enumerable property on the object
+      // we'll hijack one of the less-used non-enumerable properties to
+      // save our hash on it. Since this is a function it will not show up in
+      // `JSON.stringify` which is what we want.
+      obj.propertyIsEnumerable = function () {
+        return this.constructor.prototype.propertyIsEnumerable.apply(
+          this,
+          arguments
+        );
+      };
+      obj.propertyIsEnumerable[UID_HASH_KEY] = hashed;
+    } else if (obj.nodeType !== undefined) {
+      // At this point we couldn't get the IE `uniqueID` to use as a hash
+      // and we couldn't use a non-enumerable property to exploit the
+      // dontEnum bug so we simply add the `UID_HASH_KEY` on the node
+      // itself.
+      obj[UID_HASH_KEY] = hashed;
+    } else {
+      throw new Error('Unable to set a non-enumerable property on object.');
+    }
+
+    return hashed;
+  }
+
+  // Get references to ES5 object methods.
+  var isExtensible = Object.isExtensible;
+
+  // True if Object.defineProperty works as expected. IE8 fails this test.
+  var canDefineProperty = (function () {
+    try {
+      Object.defineProperty({}, '@', {});
+      return true;
+    } catch (e) {
+      return false;
+    }
+  })();
+
+  // IE has a `uniqueID` property on DOM nodes. We can construct the hash from it
+  // and avoid memory leaks from the IE cloneNode bug.
+  function getIENodeHash(node) {
+    if (node && node.nodeType > 0) {
+      switch (node.nodeType) {
+        case 1: // Element
+          return node.uniqueID;
+        case 9: // Document
+          return node.documentElement && node.documentElement.uniqueID;
+      }
+    }
+  }
+
+  function valueOf(obj) {
+    return obj.valueOf !== defaultValueOf && typeof obj.valueOf === 'function'
+      ? obj.valueOf(obj)
+      : obj;
+  }
+
+  function nextHash() {
+    var nextHash = ++_objHashUID;
+    if (_objHashUID & 0x40000000) {
+      _objHashUID = 0;
+    }
+    return nextHash;
+  }
+
+  // If possible, use a WeakMap.
+  var usingWeakMap = typeof WeakMap === 'function';
+  var weakMap;
+  if (usingWeakMap) {
+    weakMap = new WeakMap();
+  }
+
+  var symbolMap = Object.create(null);
+
+  var _objHashUID = 0;
+
+  var UID_HASH_KEY = '__immutablehash__';
+  if (typeof Symbol === 'function') {
+    UID_HASH_KEY = Symbol(UID_HASH_KEY);
+  }
+
+  var STRING_HASH_CACHE_MIN_STRLEN = 16;
+  var STRING_HASH_CACHE_MAX_SIZE = 255;
+  var STRING_HASH_CACHE_SIZE = 0;
+  var stringHashCache = {};
+
+  var ToKeyedSequence = /*@__PURE__*/(function (KeyedSeq) {
+    function ToKeyedSequence(indexed, useKeys) {
+      this._iter = indexed;
+      this._useKeys = useKeys;
+      this.size = indexed.size;
+    }
+
+    if ( KeyedSeq ) ToKeyedSequence.__proto__ = KeyedSeq;
+    ToKeyedSequence.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
+    ToKeyedSequence.prototype.constructor = ToKeyedSequence;
+
+    ToKeyedSequence.prototype.get = function get (key, notSetValue) {
+      return this._iter.get(key, notSetValue);
+    };
+
+    ToKeyedSequence.prototype.has = function has (key) {
+      return this._iter.has(key);
+    };
+
+    ToKeyedSequence.prototype.valueSeq = function valueSeq () {
+      return this._iter.valueSeq();
+    };
+
+    ToKeyedSequence.prototype.reverse = function reverse () {
+      var this$1$1 = this;
+
+      var reversedSequence = reverseFactory(this, true);
+      if (!this._useKeys) {
+        reversedSequence.valueSeq = function () { return this$1$1._iter.toSeq().reverse(); };
+      }
+      return reversedSequence;
+    };
+
+    ToKeyedSequence.prototype.map = function map (mapper, context) {
+      var this$1$1 = this;
+
+      var mappedSequence = mapFactory(this, mapper, context);
+      if (!this._useKeys) {
+        mappedSequence.valueSeq = function () { return this$1$1._iter.toSeq().map(mapper, context); };
+      }
+      return mappedSequence;
+    };
+
+    ToKeyedSequence.prototype.__iterate = function __iterate (fn, reverse) {
+      var this$1$1 = this;
+
+      return this._iter.__iterate(function (v, k) { return fn(v, k, this$1$1); }, reverse);
+    };
+
+    ToKeyedSequence.prototype.__iterator = function __iterator (type, reverse) {
+      return this._iter.__iterator(type, reverse);
+    };
+
+    return ToKeyedSequence;
+  }(KeyedSeq));
+  ToKeyedSequence.prototype[IS_ORDERED_SYMBOL] = true;
+
+  var ToIndexedSequence = /*@__PURE__*/(function (IndexedSeq) {
+    function ToIndexedSequence(iter) {
+      this._iter = iter;
+      this.size = iter.size;
+    }
+
+    if ( IndexedSeq ) ToIndexedSequence.__proto__ = IndexedSeq;
+    ToIndexedSequence.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+    ToIndexedSequence.prototype.constructor = ToIndexedSequence;
+
+    ToIndexedSequence.prototype.includes = function includes (value) {
+      return this._iter.includes(value);
+    };
+
+    ToIndexedSequence.prototype.__iterate = function __iterate (fn, reverse) {
+      var this$1$1 = this;
+
+      var i = 0;
+      reverse && ensureSize(this);
+      return this._iter.__iterate(
+        function (v) { return fn(v, reverse ? this$1$1.size - ++i : i++, this$1$1); },
+        reverse
+      );
+    };
+
+    ToIndexedSequence.prototype.__iterator = function __iterator (type, reverse) {
+      var this$1$1 = this;
+
+      var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
+      var i = 0;
+      reverse && ensureSize(this);
+      return new Iterator(function () {
+        var step = iterator.next();
+        return step.done
+          ? step
+          : iteratorValue(
+              type,
+              reverse ? this$1$1.size - ++i : i++,
+              step.value,
+              step
+            );
+      });
+    };
+
+    return ToIndexedSequence;
+  }(IndexedSeq));
+
+  var ToSetSequence = /*@__PURE__*/(function (SetSeq) {
+    function ToSetSequence(iter) {
+      this._iter = iter;
+      this.size = iter.size;
+    }
+
+    if ( SetSeq ) ToSetSequence.__proto__ = SetSeq;
+    ToSetSequence.prototype = Object.create( SetSeq && SetSeq.prototype );
+    ToSetSequence.prototype.constructor = ToSetSequence;
+
+    ToSetSequence.prototype.has = function has (key) {
+      return this._iter.includes(key);
+    };
+
+    ToSetSequence.prototype.__iterate = function __iterate (fn, reverse) {
+      var this$1$1 = this;
+
+      return this._iter.__iterate(function (v) { return fn(v, v, this$1$1); }, reverse);
+    };
+
+    ToSetSequence.prototype.__iterator = function __iterator (type, reverse) {
+      var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
+      return new Iterator(function () {
+        var step = iterator.next();
+        return step.done
+          ? step
+          : iteratorValue(type, step.value, step.value, step);
+      });
+    };
+
+    return ToSetSequence;
+  }(SetSeq));
+
+  var FromEntriesSequence = /*@__PURE__*/(function (KeyedSeq) {
+    function FromEntriesSequence(entries) {
+      this._iter = entries;
+      this.size = entries.size;
+    }
+
+    if ( KeyedSeq ) FromEntriesSequence.__proto__ = KeyedSeq;
+    FromEntriesSequence.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
+    FromEntriesSequence.prototype.constructor = FromEntriesSequence;
+
+    FromEntriesSequence.prototype.entrySeq = function entrySeq () {
+      return this._iter.toSeq();
+    };
+
+    FromEntriesSequence.prototype.__iterate = function __iterate (fn, reverse) {
+      var this$1$1 = this;
+
+      return this._iter.__iterate(function (entry) {
+        // Check if entry exists first so array access doesn't throw for holes
+        // in the parent iteration.
+        if (entry) {
+          validateEntry(entry);
+          var indexedCollection = isCollection(entry);
+          return fn(
+            indexedCollection ? entry.get(1) : entry[1],
+            indexedCollection ? entry.get(0) : entry[0],
+            this$1$1
+          );
+        }
+      }, reverse);
+    };
+
+    FromEntriesSequence.prototype.__iterator = function __iterator (type, reverse) {
+      var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
+      return new Iterator(function () {
+        while (true) {
+          var step = iterator.next();
+          if (step.done) {
+            return step;
+          }
+          var entry = step.value;
+          // Check if entry exists first so array access doesn't throw for holes
+          // in the parent iteration.
+          if (entry) {
+            validateEntry(entry);
+            var indexedCollection = isCollection(entry);
+            return iteratorValue(
+              type,
+              indexedCollection ? entry.get(0) : entry[0],
+              indexedCollection ? entry.get(1) : entry[1],
+              step
+            );
+          }
+        }
+      });
+    };
+
+    return FromEntriesSequence;
+  }(KeyedSeq));
+
+  ToIndexedSequence.prototype.cacheResult =
+    ToKeyedSequence.prototype.cacheResult =
+    ToSetSequence.prototype.cacheResult =
+    FromEntriesSequence.prototype.cacheResult =
+      cacheResultThrough;
+
+  function flipFactory(collection) {
+    var flipSequence = makeSequence(collection);
+    flipSequence._iter = collection;
+    flipSequence.size = collection.size;
+    flipSequence.flip = function () { return collection; };
+    flipSequence.reverse = function () {
+      var reversedSequence = collection.reverse.apply(this); // super.reverse()
+      reversedSequence.flip = function () { return collection.reverse(); };
+      return reversedSequence;
+    };
+    flipSequence.has = function (key) { return collection.includes(key); };
+    flipSequence.includes = function (key) { return collection.has(key); };
+    flipSequence.cacheResult = cacheResultThrough;
+    flipSequence.__iterateUncached = function (fn, reverse) {
+      var this$1$1 = this;
+
+      return collection.__iterate(function (v, k) { return fn(k, v, this$1$1) !== false; }, reverse);
+    };
+    flipSequence.__iteratorUncached = function (type, reverse) {
+      if (type === ITERATE_ENTRIES) {
+        var iterator = collection.__iterator(type, reverse);
+        return new Iterator(function () {
+          var step = iterator.next();
+          if (!step.done) {
+            var k = step.value[0];
+            step.value[0] = step.value[1];
+            step.value[1] = k;
+          }
+          return step;
+        });
+      }
+      return collection.__iterator(
+        type === ITERATE_VALUES ? ITERATE_KEYS : ITERATE_VALUES,
+        reverse
+      );
+    };
+    return flipSequence;
+  }
+
+  function mapFactory(collection, mapper, context) {
+    var mappedSequence = makeSequence(collection);
+    mappedSequence.size = collection.size;
+    mappedSequence.has = function (key) { return collection.has(key); };
+    mappedSequence.get = function (key, notSetValue) {
+      var v = collection.get(key, NOT_SET);
+      return v === NOT_SET
+        ? notSetValue
+        : mapper.call(context, v, key, collection);
+    };
+    mappedSequence.__iterateUncached = function (fn, reverse) {
+      var this$1$1 = this;
+
+      return collection.__iterate(
+        function (v, k, c) { return fn(mapper.call(context, v, k, c), k, this$1$1) !== false; },
+        reverse
+      );
+    };
+    mappedSequence.__iteratorUncached = function (type, reverse) {
+      var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+      return new Iterator(function () {
+        var step = iterator.next();
+        if (step.done) {
+          return step;
+        }
+        var entry = step.value;
+        var key = entry[0];
+        return iteratorValue(
+          type,
+          key,
+          mapper.call(context, entry[1], key, collection),
+          step
+        );
+      });
+    };
+    return mappedSequence;
+  }
+
+  function reverseFactory(collection, useKeys) {
+    var this$1$1 = this;
+
+    var reversedSequence = makeSequence(collection);
+    reversedSequence._iter = collection;
+    reversedSequence.size = collection.size;
+    reversedSequence.reverse = function () { return collection; };
+    if (collection.flip) {
+      reversedSequence.flip = function () {
+        var flipSequence = flipFactory(collection);
+        flipSequence.reverse = function () { return collection.flip(); };
+        return flipSequence;
+      };
+    }
+    reversedSequence.get = function (key, notSetValue) { return collection.get(useKeys ? key : -1 - key, notSetValue); };
+    reversedSequence.has = function (key) { return collection.has(useKeys ? key : -1 - key); };
+    reversedSequence.includes = function (value) { return collection.includes(value); };
+    reversedSequence.cacheResult = cacheResultThrough;
+    reversedSequence.__iterate = function (fn, reverse) {
+      var this$1$1 = this;
+
+      var i = 0;
+      reverse && ensureSize(collection);
+      return collection.__iterate(
+        function (v, k) { return fn(v, useKeys ? k : reverse ? this$1$1.size - ++i : i++, this$1$1); },
+        !reverse
+      );
+    };
+    reversedSequence.__iterator = function (type, reverse) {
+      var i = 0;
+      reverse && ensureSize(collection);
+      var iterator = collection.__iterator(ITERATE_ENTRIES, !reverse);
+      return new Iterator(function () {
+        var step = iterator.next();
+        if (step.done) {
+          return step;
+        }
+        var entry = step.value;
+        return iteratorValue(
+          type,
+          useKeys ? entry[0] : reverse ? this$1$1.size - ++i : i++,
+          entry[1],
+          step
+        );
+      });
+    };
+    return reversedSequence;
+  }
+
+  function filterFactory(collection, predicate, context, useKeys) {
+    var filterSequence = makeSequence(collection);
+    if (useKeys) {
+      filterSequence.has = function (key) {
+        var v = collection.get(key, NOT_SET);
+        return v !== NOT_SET && !!predicate.call(context, v, key, collection);
+      };
+      filterSequence.get = function (key, notSetValue) {
+        var v = collection.get(key, NOT_SET);
+        return v !== NOT_SET && predicate.call(context, v, key, collection)
+          ? v
+          : notSetValue;
+      };
+    }
+    filterSequence.__iterateUncached = function (fn, reverse) {
+      var this$1$1 = this;
+
+      var iterations = 0;
+      collection.__iterate(function (v, k, c) {
+        if (predicate.call(context, v, k, c)) {
+          iterations++;
+          return fn(v, useKeys ? k : iterations - 1, this$1$1);
+        }
+      }, reverse);
+      return iterations;
+    };
+    filterSequence.__iteratorUncached = function (type, reverse) {
+      var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+      var iterations = 0;
+      return new Iterator(function () {
+        while (true) {
+          var step = iterator.next();
+          if (step.done) {
+            return step;
+          }
+          var entry = step.value;
+          var key = entry[0];
+          var value = entry[1];
+          if (predicate.call(context, value, key, collection)) {
+            return iteratorValue(type, useKeys ? key : iterations++, value, step);
+          }
+        }
+      });
+    };
+    return filterSequence;
+  }
+
+  function countByFactory(collection, grouper, context) {
+    var groups = Map().asMutable();
+    collection.__iterate(function (v, k) {
+      groups.update(grouper.call(context, v, k, collection), 0, function (a) { return a + 1; });
+    });
+    return groups.asImmutable();
+  }
+
+  function groupByFactory(collection, grouper, context) {
+    var isKeyedIter = isKeyed(collection);
+    var groups = (isOrdered(collection) ? OrderedMap() : Map()).asMutable();
+    collection.__iterate(function (v, k) {
+      groups.update(
+        grouper.call(context, v, k, collection),
+        function (a) { return ((a = a || []), a.push(isKeyedIter ? [k, v] : v), a); }
+      );
+    });
+    var coerce = collectionClass(collection);
+    return groups.map(function (arr) { return reify(collection, coerce(arr)); }).asImmutable();
+  }
+
+  function partitionFactory(collection, predicate, context) {
+    var isKeyedIter = isKeyed(collection);
+    var groups = [[], []];
+    collection.__iterate(function (v, k) {
+      groups[predicate.call(context, v, k, collection) ? 1 : 0].push(
+        isKeyedIter ? [k, v] : v
+      );
+    });
+    var coerce = collectionClass(collection);
+    return groups.map(function (arr) { return reify(collection, coerce(arr)); });
+  }
+
+  function sliceFactory(collection, begin, end, useKeys) {
+    var originalSize = collection.size;
+
+    if (wholeSlice(begin, end, originalSize)) {
+      return collection;
+    }
+
+    // begin or end can not be resolved if they were provided as negative numbers and
+    // this collection's size is unknown. In that case, cache first so there is
+    // a known size and these do not resolve to NaN.
+    if (typeof originalSize === 'undefined' && (begin < 0 || end < 0)) {
+      return sliceFactory(collection.toSeq().cacheResult(), begin, end, useKeys);
+    }
+
+    var resolvedBegin = resolveBegin(begin, originalSize);
+    var resolvedEnd = resolveEnd(end, originalSize);
+
+    // Note: resolvedEnd is undefined when the original sequence's length is
+    // unknown and this slice did not supply an end and should contain all
+    // elements after resolvedBegin.
+    // In that case, resolvedSize will be NaN and sliceSize will remain undefined.
+    var resolvedSize = resolvedEnd - resolvedBegin;
+    var sliceSize;
+    if (resolvedSize === resolvedSize) {
+      sliceSize = resolvedSize < 0 ? 0 : resolvedSize;
+    }
+
+    var sliceSeq = makeSequence(collection);
+
+    // If collection.size is undefined, the size of the realized sliceSeq is
+    // unknown at this point unless the number of items to slice is 0
+    sliceSeq.size =
+      sliceSize === 0 ? sliceSize : (collection.size && sliceSize) || undefined;
+
+    if (!useKeys && isSeq(collection) && sliceSize >= 0) {
+      sliceSeq.get = function (index, notSetValue) {
+        index = wrapIndex(this, index);
+        return index >= 0 && index < sliceSize
+          ? collection.get(index + resolvedBegin, notSetValue)
+          : notSetValue;
+      };
+    }
+
+    sliceSeq.__iterateUncached = function (fn, reverse) {
+      var this$1$1 = this;
+
+      if (sliceSize === 0) {
+        return 0;
+      }
+      if (reverse) {
+        return this.cacheResult().__iterate(fn, reverse);
+      }
+      var skipped = 0;
+      var isSkipping = true;
+      var iterations = 0;
+      collection.__iterate(function (v, k) {
+        if (!(isSkipping && (isSkipping = skipped++ < resolvedBegin))) {
+          iterations++;
+          return (
+            fn(v, useKeys ? k : iterations - 1, this$1$1) !== false &&
+            iterations !== sliceSize
+          );
+        }
+      });
+      return iterations;
+    };
+
+    sliceSeq.__iteratorUncached = function (type, reverse) {
+      if (sliceSize !== 0 && reverse) {
+        return this.cacheResult().__iterator(type, reverse);
+      }
+      // Don't bother instantiating parent iterator if taking 0.
+      if (sliceSize === 0) {
+        return new Iterator(iteratorDone);
+      }
+      var iterator = collection.__iterator(type, reverse);
+      var skipped = 0;
+      var iterations = 0;
+      return new Iterator(function () {
+        while (skipped++ < resolvedBegin) {
+          iterator.next();
+        }
+        if (++iterations > sliceSize) {
+          return iteratorDone();
+        }
+        var step = iterator.next();
+        if (useKeys || type === ITERATE_VALUES || step.done) {
+          return step;
+        }
+        if (type === ITERATE_KEYS) {
+          return iteratorValue(type, iterations - 1, undefined, step);
+        }
+        return iteratorValue(type, iterations - 1, step.value[1], step);
+      });
+    };
+
+    return sliceSeq;
+  }
+
+  function takeWhileFactory(collection, predicate, context) {
+    var takeSequence = makeSequence(collection);
+    takeSequence.__iterateUncached = function (fn, reverse) {
+      var this$1$1 = this;
+
+      if (reverse) {
+        return this.cacheResult().__iterate(fn, reverse);
+      }
+      var iterations = 0;
+      collection.__iterate(
+        function (v, k, c) { return predicate.call(context, v, k, c) && ++iterations && fn(v, k, this$1$1); }
+      );
+      return iterations;
+    };
+    takeSequence.__iteratorUncached = function (type, reverse) {
+      var this$1$1 = this;
+
+      if (reverse) {
+        return this.cacheResult().__iterator(type, reverse);
+      }
+      var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+      var iterating = true;
+      return new Iterator(function () {
+        if (!iterating) {
+          return iteratorDone();
+        }
+        var step = iterator.next();
+        if (step.done) {
+          return step;
+        }
+        var entry = step.value;
+        var k = entry[0];
+        var v = entry[1];
+        if (!predicate.call(context, v, k, this$1$1)) {
+          iterating = false;
+          return iteratorDone();
+        }
+        return type === ITERATE_ENTRIES ? step : iteratorValue(type, k, v, step);
+      });
+    };
+    return takeSequence;
+  }
+
+  function skipWhileFactory(collection, predicate, context, useKeys) {
+    var skipSequence = makeSequence(collection);
+    skipSequence.__iterateUncached = function (fn, reverse) {
+      var this$1$1 = this;
+
+      if (reverse) {
+        return this.cacheResult().__iterate(fn, reverse);
+      }
+      var isSkipping = true;
+      var iterations = 0;
+      collection.__iterate(function (v, k, c) {
+        if (!(isSkipping && (isSkipping = predicate.call(context, v, k, c)))) {
+          iterations++;
+          return fn(v, useKeys ? k : iterations - 1, this$1$1);
+        }
+      });
+      return iterations;
+    };
+    skipSequence.__iteratorUncached = function (type, reverse) {
+      var this$1$1 = this;
+
+      if (reverse) {
+        return this.cacheResult().__iterator(type, reverse);
+      }
+      var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+      var skipping = true;
+      var iterations = 0;
+      return new Iterator(function () {
+        var step;
+        var k;
+        var v;
+        do {
+          step = iterator.next();
+          if (step.done) {
+            if (useKeys || type === ITERATE_VALUES) {
+              return step;
+            }
+            if (type === ITERATE_KEYS) {
+              return iteratorValue(type, iterations++, undefined, step);
+            }
+            return iteratorValue(type, iterations++, step.value[1], step);
+          }
+          var entry = step.value;
+          k = entry[0];
+          v = entry[1];
+          skipping && (skipping = predicate.call(context, v, k, this$1$1));
+        } while (skipping);
+        return type === ITERATE_ENTRIES ? step : iteratorValue(type, k, v, step);
+      });
+    };
+    return skipSequence;
+  }
+
+  function concatFactory(collection, values) {
+    var isKeyedCollection = isKeyed(collection);
+    var iters = [collection]
+      .concat(values)
+      .map(function (v) {
+        if (!isCollection(v)) {
+          v = isKeyedCollection
+            ? keyedSeqFromValue(v)
+            : indexedSeqFromValue(Array.isArray(v) ? v : [v]);
+        } else if (isKeyedCollection) {
+          v = KeyedCollection(v);
+        }
+        return v;
+      })
+      .filter(function (v) { return v.size !== 0; });
+
+    if (iters.length === 0) {
+      return collection;
+    }
+
+    if (iters.length === 1) {
+      var singleton = iters[0];
+      if (
+        singleton === collection ||
+        (isKeyedCollection && isKeyed(singleton)) ||
+        (isIndexed(collection) && isIndexed(singleton))
+      ) {
+        return singleton;
+      }
+    }
+
+    var concatSeq = new ArraySeq(iters);
+    if (isKeyedCollection) {
+      concatSeq = concatSeq.toKeyedSeq();
+    } else if (!isIndexed(collection)) {
+      concatSeq = concatSeq.toSetSeq();
+    }
+    concatSeq = concatSeq.flatten(true);
+    concatSeq.size = iters.reduce(function (sum, seq) {
+      if (sum !== undefined) {
+        var size = seq.size;
+        if (size !== undefined) {
+          return sum + size;
+        }
+      }
+    }, 0);
+    return concatSeq;
+  }
+
+  function flattenFactory(collection, depth, useKeys) {
+    var flatSequence = makeSequence(collection);
+    flatSequence.__iterateUncached = function (fn, reverse) {
+      if (reverse) {
+        return this.cacheResult().__iterate(fn, reverse);
+      }
+      var iterations = 0;
+      var stopped = false;
+      function flatDeep(iter, currentDepth) {
+        iter.__iterate(function (v, k) {
+          if ((!depth || currentDepth < depth) && isCollection(v)) {
+            flatDeep(v, currentDepth + 1);
+          } else {
+            iterations++;
+            if (fn(v, useKeys ? k : iterations - 1, flatSequence) === false) {
+              stopped = true;
+            }
+          }
+          return !stopped;
+        }, reverse);
+      }
+      flatDeep(collection, 0);
+      return iterations;
+    };
+    flatSequence.__iteratorUncached = function (type, reverse) {
+      if (reverse) {
+        return this.cacheResult().__iterator(type, reverse);
+      }
+      var iterator = collection.__iterator(type, reverse);
+      var stack = [];
+      var iterations = 0;
+      return new Iterator(function () {
+        while (iterator) {
+          var step = iterator.next();
+          if (step.done !== false) {
+            iterator = stack.pop();
+            continue;
+          }
+          var v = step.value;
+          if (type === ITERATE_ENTRIES) {
+            v = v[1];
+          }
+          if ((!depth || stack.length < depth) && isCollection(v)) {
+            stack.push(iterator);
+            iterator = v.__iterator(type, reverse);
+          } else {
+            return useKeys ? step : iteratorValue(type, iterations++, v, step);
+          }
+        }
+        return iteratorDone();
+      });
+    };
+    return flatSequence;
+  }
+
+  function flatMapFactory(collection, mapper, context) {
+    var coerce = collectionClass(collection);
+    return collection
+      .toSeq()
+      .map(function (v, k) { return coerce(mapper.call(context, v, k, collection)); })
+      .flatten(true);
+  }
+
+  function interposeFactory(collection, separator) {
+    var interposedSequence = makeSequence(collection);
+    interposedSequence.size = collection.size && collection.size * 2 - 1;
+    interposedSequence.__iterateUncached = function (fn, reverse) {
+      var this$1$1 = this;
+
+      var iterations = 0;
+      collection.__iterate(
+        function (v) { return (!iterations || fn(separator, iterations++, this$1$1) !== false) &&
+          fn(v, iterations++, this$1$1) !== false; },
+        reverse
+      );
+      return iterations;
+    };
+    interposedSequence.__iteratorUncached = function (type, reverse) {
+      var iterator = collection.__iterator(ITERATE_VALUES, reverse);
+      var iterations = 0;
+      var step;
+      return new Iterator(function () {
+        if (!step || iterations % 2) {
+          step = iterator.next();
+          if (step.done) {
+            return step;
+          }
+        }
+        return iterations % 2
+          ? iteratorValue(type, iterations++, separator)
+          : iteratorValue(type, iterations++, step.value, step);
+      });
+    };
+    return interposedSequence;
+  }
+
+  function sortFactory(collection, comparator, mapper) {
+    if (!comparator) {
+      comparator = defaultComparator;
+    }
+    var isKeyedCollection = isKeyed(collection);
+    var index = 0;
+    var entries = collection
+      .toSeq()
+      .map(function (v, k) { return [k, v, index++, mapper ? mapper(v, k, collection) : v]; })
+      .valueSeq()
+      .toArray();
+    entries
+      .sort(function (a, b) { return comparator(a[3], b[3]) || a[2] - b[2]; })
+      .forEach(
+        isKeyedCollection
+          ? function (v, i) {
+              entries[i].length = 2;
+            }
+          : function (v, i) {
+              entries[i] = v[1];
+            }
+      );
+    return isKeyedCollection
+      ? KeyedSeq(entries)
+      : isIndexed(collection)
+      ? IndexedSeq(entries)
+      : SetSeq(entries);
+  }
+
+  function maxFactory(collection, comparator, mapper) {
+    if (!comparator) {
+      comparator = defaultComparator;
+    }
+    if (mapper) {
+      var entry = collection
+        .toSeq()
+        .map(function (v, k) { return [v, mapper(v, k, collection)]; })
+        .reduce(function (a, b) { return (maxCompare(comparator, a[1], b[1]) ? b : a); });
+      return entry && entry[0];
+    }
+    return collection.reduce(function (a, b) { return (maxCompare(comparator, a, b) ? b : a); });
+  }
+
+  function maxCompare(comparator, a, b) {
+    var comp = comparator(b, a);
+    // b is considered the new max if the comparator declares them equal, but
+    // they are not equal and b is in fact a nullish value.
+    return (
+      (comp === 0 && b !== a && (b === undefined || b === null || b !== b)) ||
+      comp > 0
+    );
+  }
+
+  function zipWithFactory(keyIter, zipper, iters, zipAll) {
+    var zipSequence = makeSequence(keyIter);
+    var sizes = new ArraySeq(iters).map(function (i) { return i.size; });
+    zipSequence.size = zipAll ? sizes.max() : sizes.min();
+    // Note: this a generic base implementation of __iterate in terms of
+    // __iterator which may be more generically useful in the future.
+    zipSequence.__iterate = function (fn, reverse) {
+      /* generic:
+      var iterator = this.__iterator(ITERATE_ENTRIES, reverse);
+      var step;
+      var iterations = 0;
+      while (!(step = iterator.next()).done) {
+        iterations++;
+        if (fn(step.value[1], step.value[0], this) === false) {
+          break;
+        }
+      }
+      return iterations;
+      */
+      // indexed:
+      var iterator = this.__iterator(ITERATE_VALUES, reverse);
+      var step;
+      var iterations = 0;
+      while (!(step = iterator.next()).done) {
+        if (fn(step.value, iterations++, this) === false) {
+          break;
+        }
+      }
+      return iterations;
+    };
+    zipSequence.__iteratorUncached = function (type, reverse) {
+      var iterators = iters.map(
+        function (i) { return ((i = Collection(i)), getIterator(reverse ? i.reverse() : i)); }
+      );
+      var iterations = 0;
+      var isDone = false;
+      return new Iterator(function () {
+        var steps;
+        if (!isDone) {
+          steps = iterators.map(function (i) { return i.next(); });
+          isDone = zipAll ? steps.every(function (s) { return s.done; }) : steps.some(function (s) { return s.done; });
+        }
+        if (isDone) {
+          return iteratorDone();
+        }
+        return iteratorValue(
+          type,
+          iterations++,
+          zipper.apply(
+            null,
+            steps.map(function (s) { return s.value; })
+          )
+        );
+      });
+    };
+    return zipSequence;
+  }
+
+  // #pragma Helper Functions
+
+  function reify(iter, seq) {
+    return iter === seq ? iter : isSeq(iter) ? seq : iter.constructor(seq);
+  }
+
+  function validateEntry(entry) {
+    if (entry !== Object(entry)) {
+      throw new TypeError('Expected [K, V] tuple: ' + entry);
+    }
+  }
+
+  function collectionClass(collection) {
+    return isKeyed(collection)
+      ? KeyedCollection
+      : isIndexed(collection)
+      ? IndexedCollection
+      : SetCollection;
+  }
+
+  function makeSequence(collection) {
+    return Object.create(
+      (isKeyed(collection)
+        ? KeyedSeq
+        : isIndexed(collection)
+        ? IndexedSeq
+        : SetSeq
+      ).prototype
+    );
+  }
+
+  function cacheResultThrough() {
+    if (this._iter.cacheResult) {
+      this._iter.cacheResult();
+      this.size = this._iter.size;
+      return this;
+    }
+    return Seq.prototype.cacheResult.call(this);
+  }
+
+  function defaultComparator(a, b) {
+    if (a === undefined && b === undefined) {
+      return 0;
+    }
+
+    if (a === undefined) {
+      return 1;
+    }
+
+    if (b === undefined) {
+      return -1;
+    }
+
+    return a > b ? 1 : a < b ? -1 : 0;
+  }
+
+  // http://jsperf.com/copy-array-inline
+  function arrCopy(arr, offset) {
+    offset = offset || 0;
+    var len = Math.max(0, arr.length - offset);
+    var newArr = new Array(len);
+    for (var ii = 0; ii < len; ii++) {
+      newArr[ii] = arr[ii + offset];
+    }
+    return newArr;
+  }
+
+  function invariant(condition, error) {
+    if (!condition) { throw new Error(error); }
+  }
+
+  function assertNotInfinite(size) {
+    invariant(
+      size !== Infinity,
+      'Cannot perform this action with an infinite size.'
+    );
+  }
+
+  function coerceKeyPath(keyPath) {
+    if (isArrayLike(keyPath) && typeof keyPath !== 'string') {
+      return keyPath;
+    }
+    if (isOrdered(keyPath)) {
+      return keyPath.toArray();
+    }
+    throw new TypeError(
+      'Invalid keyPath: expected Ordered Collection or Array: ' + keyPath
+    );
+  }
+
+  var toString = Object.prototype.toString;
+
+  function isPlainObject(value) {
+    // The base prototype's toString deals with Argument objects and native namespaces like Math
+    if (
+      !value ||
+      typeof value !== 'object' ||
+      toString.call(value) !== '[object Object]'
+    ) {
+      return false;
+    }
+
+    var proto = Object.getPrototypeOf(value);
+    if (proto === null) {
+      return true;
+    }
+
+    // Iteratively going up the prototype chain is needed for cross-realm environments (differing contexts, iframes, etc)
+    var parentProto = proto;
+    var nextProto = Object.getPrototypeOf(proto);
+    while (nextProto !== null) {
+      parentProto = nextProto;
+      nextProto = Object.getPrototypeOf(parentProto);
+    }
+    return parentProto === proto;
+  }
+
+  /**
+   * Returns true if the value is a potentially-persistent data structure, either
+   * provided by Immutable.js or a plain Array or Object.
+   */
+  function isDataStructure(value) {
+    return (
+      typeof value === 'object' &&
+      (isImmutable(value) || Array.isArray(value) || isPlainObject(value))
+    );
+  }
+
+  /**
+   * Converts a value to a string, adding quotes if a string was provided.
+   */
+  function quoteString(value) {
+    try {
+      return typeof value === 'string' ? JSON.stringify(value) : String(value);
+    } catch (_ignoreError) {
+      return JSON.stringify(value);
+    }
+  }
+
+  function has(collection, key) {
+    return isImmutable(collection)
+      ? collection.has(key)
+      : isDataStructure(collection) && hasOwnProperty.call(collection, key);
+  }
+
+  function get(collection, key, notSetValue) {
+    return isImmutable(collection)
+      ? collection.get(key, notSetValue)
+      : !has(collection, key)
+      ? notSetValue
+      : typeof collection.get === 'function'
+      ? collection.get(key)
+      : collection[key];
+  }
+
+  function shallowCopy(from) {
+    if (Array.isArray(from)) {
+      return arrCopy(from);
+    }
+    var to = {};
+    for (var key in from) {
+      if (hasOwnProperty.call(from, key)) {
+        to[key] = from[key];
+      }
+    }
+    return to;
+  }
+
+  function remove(collection, key) {
+    if (!isDataStructure(collection)) {
+      throw new TypeError(
+        'Cannot update non-data-structure value: ' + collection
+      );
+    }
+    if (isImmutable(collection)) {
+      if (!collection.remove) {
+        throw new TypeError(
+          'Cannot update immutable value without .remove() method: ' + collection
+        );
+      }
+      return collection.remove(key);
+    }
+    if (!hasOwnProperty.call(collection, key)) {
+      return collection;
+    }
+    var collectionCopy = shallowCopy(collection);
+    if (Array.isArray(collectionCopy)) {
+      collectionCopy.splice(key, 1);
+    } else {
+      delete collectionCopy[key];
+    }
+    return collectionCopy;
+  }
+
+  function set(collection, key, value) {
+    if (!isDataStructure(collection)) {
+      throw new TypeError(
+        'Cannot update non-data-structure value: ' + collection
+      );
+    }
+    if (isImmutable(collection)) {
+      if (!collection.set) {
+        throw new TypeError(
+          'Cannot update immutable value without .set() method: ' + collection
+        );
+      }
+      return collection.set(key, value);
+    }
+    if (hasOwnProperty.call(collection, key) && value === collection[key]) {
+      return collection;
+    }
+    var collectionCopy = shallowCopy(collection);
+    collectionCopy[key] = value;
+    return collectionCopy;
+  }
+
+  function updateIn$1(collection, keyPath, notSetValue, updater) {
+    if (!updater) {
+      updater = notSetValue;
+      notSetValue = undefined;
+    }
+    var updatedValue = updateInDeeply(
+      isImmutable(collection),
+      collection,
+      coerceKeyPath(keyPath),
+      0,
+      notSetValue,
+      updater
+    );
+    return updatedValue === NOT_SET ? notSetValue : updatedValue;
+  }
+
+  function updateInDeeply(
+    inImmutable,
+    existing,
+    keyPath,
+    i,
+    notSetValue,
+    updater
+  ) {
+    var wasNotSet = existing === NOT_SET;
+    if (i === keyPath.length) {
+      var existingValue = wasNotSet ? notSetValue : existing;
+      var newValue = updater(existingValue);
+      return newValue === existingValue ? existing : newValue;
+    }
+    if (!wasNotSet && !isDataStructure(existing)) {
+      throw new TypeError(
+        'Cannot update within non-data-structure value in path [' +
+          keyPath.slice(0, i).map(quoteString) +
+          ']: ' +
+          existing
+      );
+    }
+    var key = keyPath[i];
+    var nextExisting = wasNotSet ? NOT_SET : get(existing, key, NOT_SET);
+    var nextUpdated = updateInDeeply(
+      nextExisting === NOT_SET ? inImmutable : isImmutable(nextExisting),
+      nextExisting,
+      keyPath,
+      i + 1,
+      notSetValue,
+      updater
+    );
+    return nextUpdated === nextExisting
+      ? existing
+      : nextUpdated === NOT_SET
+      ? remove(existing, key)
+      : set(
+          wasNotSet ? (inImmutable ? emptyMap() : {}) : existing,
+          key,
+          nextUpdated
+        );
+  }
+
+  function setIn$1(collection, keyPath, value) {
+    return updateIn$1(collection, keyPath, NOT_SET, function () { return value; });
+  }
+
+  function setIn(keyPath, v) {
+    return setIn$1(this, keyPath, v);
+  }
+
+  function removeIn(collection, keyPath) {
+    return updateIn$1(collection, keyPath, function () { return NOT_SET; });
+  }
+
+  function deleteIn(keyPath) {
+    return removeIn(this, keyPath);
+  }
+
+  function update$1(collection, key, notSetValue, updater) {
+    return updateIn$1(collection, [key], notSetValue, updater);
+  }
+
+  function update(key, notSetValue, updater) {
+    return arguments.length === 1
+      ? key(this)
+      : update$1(this, key, notSetValue, updater);
+  }
+
+  function updateIn(keyPath, notSetValue, updater) {
+    return updateIn$1(this, keyPath, notSetValue, updater);
+  }
+
+  function merge$1() {
+    var iters = [], len = arguments.length;
+    while ( len-- ) iters[ len ] = arguments[ len ];
+
+    return mergeIntoKeyedWith(this, iters);
+  }
+
+  function mergeWith$1(merger) {
+    var iters = [], len = arguments.length - 1;
+    while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+    if (typeof merger !== 'function') {
+      throw new TypeError('Invalid merger function: ' + merger);
+    }
+    return mergeIntoKeyedWith(this, iters, merger);
+  }
+
+  function mergeIntoKeyedWith(collection, collections, merger) {
+    var iters = [];
+    for (var ii = 0; ii < collections.length; ii++) {
+      var collection$1 = KeyedCollection(collections[ii]);
+      if (collection$1.size !== 0) {
+        iters.push(collection$1);
+      }
+    }
+    if (iters.length === 0) {
+      return collection;
+    }
+    if (
+      collection.toSeq().size === 0 &&
+      !collection.__ownerID &&
+      iters.length === 1
+    ) {
+      return collection.constructor(iters[0]);
+    }
+    return collection.withMutations(function (collection) {
+      var mergeIntoCollection = merger
+        ? function (value, key) {
+            update$1(collection, key, NOT_SET, function (oldVal) { return oldVal === NOT_SET ? value : merger(oldVal, value, key); }
+            );
+          }
+        : function (value, key) {
+            collection.set(key, value);
+          };
+      for (var ii = 0; ii < iters.length; ii++) {
+        iters[ii].forEach(mergeIntoCollection);
+      }
+    });
+  }
+
+  function merge(collection) {
+    var sources = [], len = arguments.length - 1;
+    while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];
+
+    return mergeWithSources(collection, sources);
+  }
+
+  function mergeWith(merger, collection) {
+    var sources = [], len = arguments.length - 2;
+    while ( len-- > 0 ) sources[ len ] = arguments[ len + 2 ];
+
+    return mergeWithSources(collection, sources, merger);
+  }
+
+  function mergeDeep$1(collection) {
+    var sources = [], len = arguments.length - 1;
+    while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];
+
+    return mergeDeepWithSources(collection, sources);
+  }
+
+  function mergeDeepWith$1(merger, collection) {
+    var sources = [], len = arguments.length - 2;
+    while ( len-- > 0 ) sources[ len ] = arguments[ len + 2 ];
+
+    return mergeDeepWithSources(collection, sources, merger);
+  }
+
+  function mergeDeepWithSources(collection, sources, merger) {
+    return mergeWithSources(collection, sources, deepMergerWith(merger));
+  }
+
+  function mergeWithSources(collection, sources, merger) {
+    if (!isDataStructure(collection)) {
+      throw new TypeError(
+        'Cannot merge into non-data-structure value: ' + collection
+      );
+    }
+    if (isImmutable(collection)) {
+      return typeof merger === 'function' && collection.mergeWith
+        ? collection.mergeWith.apply(collection, [ merger ].concat( sources ))
+        : collection.merge
+        ? collection.merge.apply(collection, sources)
+        : collection.concat.apply(collection, sources);
+    }
+    var isArray = Array.isArray(collection);
+    var merged = collection;
+    var Collection = isArray ? IndexedCollection : KeyedCollection;
+    var mergeItem = isArray
+      ? function (value) {
+          // Copy on write
+          if (merged === collection) {
+            merged = shallowCopy(merged);
+          }
+          merged.push(value);
+        }
+      : function (value, key) {
+          var hasVal = hasOwnProperty.call(merged, key);
+          var nextVal =
+            hasVal && merger ? merger(merged[key], value, key) : value;
+          if (!hasVal || nextVal !== merged[key]) {
+            // Copy on write
+            if (merged === collection) {
+              merged = shallowCopy(merged);
+            }
+            merged[key] = nextVal;
+          }
+        };
+    for (var i = 0; i < sources.length; i++) {
+      Collection(sources[i]).forEach(mergeItem);
+    }
+    return merged;
+  }
+
+  function deepMergerWith(merger) {
+    function deepMerger(oldValue, newValue, key) {
+      return isDataStructure(oldValue) &&
+        isDataStructure(newValue) &&
+        areMergeable(oldValue, newValue)
+        ? mergeWithSources(oldValue, [newValue], deepMerger)
+        : merger
+        ? merger(oldValue, newValue, key)
+        : newValue;
+    }
+    return deepMerger;
+  }
+
+  /**
+   * It's unclear what the desired behavior is for merging two collections that
+   * fall into separate categories between keyed, indexed, or set-like, so we only
+   * consider them mergeable if they fall into the same category.
+   */
+  function areMergeable(oldDataStructure, newDataStructure) {
+    var oldSeq = Seq(oldDataStructure);
+    var newSeq = Seq(newDataStructure);
+    // This logic assumes that a sequence can only fall into one of the three
+    // categories mentioned above (since there's no `isSetLike()` method).
+    return (
+      isIndexed(oldSeq) === isIndexed(newSeq) &&
+      isKeyed(oldSeq) === isKeyed(newSeq)
+    );
+  }
+
+  function mergeDeep() {
+    var iters = [], len = arguments.length;
+    while ( len-- ) iters[ len ] = arguments[ len ];
+
+    return mergeDeepWithSources(this, iters);
+  }
+
+  function mergeDeepWith(merger) {
+    var iters = [], len = arguments.length - 1;
+    while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+    return mergeDeepWithSources(this, iters, merger);
+  }
+
+  function mergeIn(keyPath) {
+    var iters = [], len = arguments.length - 1;
+    while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+    return updateIn$1(this, keyPath, emptyMap(), function (m) { return mergeWithSources(m, iters); });
+  }
+
+  function mergeDeepIn(keyPath) {
+    var iters = [], len = arguments.length - 1;
+    while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+    return updateIn$1(this, keyPath, emptyMap(), function (m) { return mergeDeepWithSources(m, iters); }
+    );
+  }
+
+  function withMutations(fn) {
+    var mutable = this.asMutable();
+    fn(mutable);
+    return mutable.wasAltered() ? mutable.__ensureOwner(this.__ownerID) : this;
+  }
+
+  function asMutable() {
+    return this.__ownerID ? this : this.__ensureOwner(new OwnerID());
+  }
+
+  function asImmutable() {
+    return this.__ensureOwner();
+  }
+
+  function wasAltered() {
+    return this.__altered;
+  }
+
+  var Map = /*@__PURE__*/(function (KeyedCollection) {
+    function Map(value) {
+      // eslint-disable-next-line no-constructor-return
+      return value === undefined || value === null
+        ? emptyMap()
+        : isMap(value) && !isOrdered(value)
+        ? value
+        : emptyMap().withMutations(function (map) {
+            var iter = KeyedCollection(value);
+            assertNotInfinite(iter.size);
+            iter.forEach(function (v, k) { return map.set(k, v); });
+          });
+    }
+
+    if ( KeyedCollection ) Map.__proto__ = KeyedCollection;
+    Map.prototype = Object.create( KeyedCollection && KeyedCollection.prototype );
+    Map.prototype.constructor = Map;
+
+    Map.prototype.toString = function toString () {
+      return this.__toString('Map {', '}');
+    };
+
+    // @pragma Access
+
+    Map.prototype.get = function get (k, notSetValue) {
+      return this._root
+        ? this._root.get(0, undefined, k, notSetValue)
+        : notSetValue;
+    };
+
+    // @pragma Modification
+
+    Map.prototype.set = function set (k, v) {
+      return updateMap(this, k, v);
+    };
+
+    Map.prototype.remove = function remove (k) {
+      return updateMap(this, k, NOT_SET);
+    };
+
+    Map.prototype.deleteAll = function deleteAll (keys) {
+      var collection = Collection(keys);
+
+      if (collection.size === 0) {
+        return this;
+      }
+
+      return this.withMutations(function (map) {
+        collection.forEach(function (key) { return map.remove(key); });
+      });
+    };
+
+    Map.prototype.clear = function clear () {
+      if (this.size === 0) {
+        return this;
+      }
+      if (this.__ownerID) {
+        this.size = 0;
+        this._root = null;
+        this.__hash = undefined;
+        this.__altered = true;
+        return this;
+      }
+      return emptyMap();
+    };
+
+    // @pragma Composition
+
+    Map.prototype.sort = function sort (comparator) {
+      // Late binding
+      return OrderedMap(sortFactory(this, comparator));
+    };
+
+    Map.prototype.sortBy = function sortBy (mapper, comparator) {
+      // Late binding
+      return OrderedMap(sortFactory(this, comparator, mapper));
+    };
+
+    Map.prototype.map = function map (mapper, context) {
+      var this$1$1 = this;
+
+      return this.withMutations(function (map) {
+        map.forEach(function (value, key) {
+          map.set(key, mapper.call(context, value, key, this$1$1));
+        });
+      });
+    };
+
+    // @pragma Mutability
+
+    Map.prototype.__iterator = function __iterator (type, reverse) {
+      return new MapIterator(this, type, reverse);
+    };
+
+    Map.prototype.__iterate = function __iterate (fn, reverse) {
+      var this$1$1 = this;
+
+      var iterations = 0;
+      this._root &&
+        this._root.iterate(function (entry) {
+          iterations++;
+          return fn(entry[1], entry[0], this$1$1);
+        }, reverse);
+      return iterations;
+    };
+
+    Map.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+      if (ownerID === this.__ownerID) {
+        return this;
+      }
+      if (!ownerID) {
+        if (this.size === 0) {
+          return emptyMap();
+        }
+        this.__ownerID = ownerID;
+        this.__altered = false;
+        return this;
+      }
+      return makeMap(this.size, this._root, ownerID, this.__hash);
+    };
+
+    return Map;
+  }(KeyedCollection));
+
+  Map.isMap = isMap;
+
+  var MapPrototype = Map.prototype;
+  MapPrototype[IS_MAP_SYMBOL] = true;
+  MapPrototype[DELETE] = MapPrototype.remove;
+  MapPrototype.removeAll = MapPrototype.deleteAll;
+  MapPrototype.setIn = setIn;
+  MapPrototype.removeIn = MapPrototype.deleteIn = deleteIn;
+  MapPrototype.update = update;
+  MapPrototype.updateIn = updateIn;
+  MapPrototype.merge = MapPrototype.concat = merge$1;
+  MapPrototype.mergeWith = mergeWith$1;
+  MapPrototype.mergeDeep = mergeDeep;
+  MapPrototype.mergeDeepWith = mergeDeepWith;
+  MapPrototype.mergeIn = mergeIn;
+  MapPrototype.mergeDeepIn = mergeDeepIn;
+  MapPrototype.withMutations = withMutations;
+  MapPrototype.wasAltered = wasAltered;
+  MapPrototype.asImmutable = asImmutable;
+  MapPrototype['@@transducer/init'] = MapPrototype.asMutable = asMutable;
+  MapPrototype['@@transducer/step'] = function (result, arr) {
+    return result.set(arr[0], arr[1]);
+  };
+  MapPrototype['@@transducer/result'] = function (obj) {
+    return obj.asImmutable();
+  };
+
+  // #pragma Trie Nodes
+
+  var ArrayMapNode = function ArrayMapNode(ownerID, entries) {
+    this.ownerID = ownerID;
+    this.entries = entries;
+  };
+
+  ArrayMapNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+    var entries = this.entries;
+    for (var ii = 0, len = entries.length; ii < len; ii++) {
+      if (is(key, entries[ii][0])) {
+        return entries[ii][1];
+      }
+    }
+    return notSetValue;
+  };
+
+  ArrayMapNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+    var removed = value === NOT_SET;
+
+    var entries = this.entries;
+    var idx = 0;
+    var len = entries.length;
+    for (; idx < len; idx++) {
+      if (is(key, entries[idx][0])) {
+        break;
+      }
+    }
+    var exists = idx < len;
+
+    if (exists ? entries[idx][1] === value : removed) {
+      return this;
+    }
+
+    SetRef(didAlter);
+    (removed || !exists) && SetRef(didChangeSize);
+
+    if (removed && entries.length === 1) {
+      return; // undefined
+    }
+
+    if (!exists && !removed && entries.length >= MAX_ARRAY_MAP_SIZE) {
+      return createNodes(ownerID, entries, key, value);
+    }
+
+    var isEditable = ownerID && ownerID === this.ownerID;
+    var newEntries = isEditable ? entries : arrCopy(entries);
+
+    if (exists) {
+      if (removed) {
+        idx === len - 1
+          ? newEntries.pop()
+          : (newEntries[idx] = newEntries.pop());
+      } else {
+        newEntries[idx] = [key, value];
+      }
+    } else {
+      newEntries.push([key, value]);
+    }
+
+    if (isEditable) {
+      this.entries = newEntries;
+      return this;
+    }
+
+    return new ArrayMapNode(ownerID, newEntries);
+  };
+
+  var BitmapIndexedNode = function BitmapIndexedNode(ownerID, bitmap, nodes) {
+    this.ownerID = ownerID;
+    this.bitmap = bitmap;
+    this.nodes = nodes;
+  };
+
+  BitmapIndexedNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+    if (keyHash === undefined) {
+      keyHash = hash(key);
+    }
+    var bit = 1 << ((shift === 0 ? keyHash : keyHash >>> shift) & MASK);
+    var bitmap = this.bitmap;
+    return (bitmap & bit) === 0
+      ? notSetValue
+      : this.nodes[popCount(bitmap & (bit - 1))].get(
+          shift + SHIFT,
+          keyHash,
+          key,
+          notSetValue
+        );
+  };
+
+  BitmapIndexedNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+    if (keyHash === undefined) {
+      keyHash = hash(key);
+    }
+    var keyHashFrag = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+    var bit = 1 << keyHashFrag;
+    var bitmap = this.bitmap;
+    var exists = (bitmap & bit) !== 0;
+
+    if (!exists && value === NOT_SET) {
+      return this;
+    }
+
+    var idx = popCount(bitmap & (bit - 1));
+    var nodes = this.nodes;
+    var node = exists ? nodes[idx] : undefined;
+    var newNode = updateNode(
+      node,
+      ownerID,
+      shift + SHIFT,
+      keyHash,
+      key,
+      value,
+      didChangeSize,
+      didAlter
+    );
+
+    if (newNode === node) {
+      return this;
+    }
+
+    if (!exists && newNode && nodes.length >= MAX_BITMAP_INDEXED_SIZE) {
+      return expandNodes(ownerID, nodes, bitmap, keyHashFrag, newNode);
+    }
+
+    if (
+      exists &&
+      !newNode &&
+      nodes.length === 2 &&
+      isLeafNode(nodes[idx ^ 1])
+    ) {
+      return nodes[idx ^ 1];
+    }
+
+    if (exists && newNode && nodes.length === 1 && isLeafNode(newNode)) {
+      return newNode;
+    }
+
+    var isEditable = ownerID && ownerID === this.ownerID;
+    var newBitmap = exists ? (newNode ? bitmap : bitmap ^ bit) : bitmap | bit;
+    var newNodes = exists
+      ? newNode
+        ? setAt(nodes, idx, newNode, isEditable)
+        : spliceOut(nodes, idx, isEditable)
+      : spliceIn(nodes, idx, newNode, isEditable);
+
+    if (isEditable) {
+      this.bitmap = newBitmap;
+      this.nodes = newNodes;
+      return this;
+    }
+
+    return new BitmapIndexedNode(ownerID, newBitmap, newNodes);
+  };
+
+  var HashArrayMapNode = function HashArrayMapNode(ownerID, count, nodes) {
+    this.ownerID = ownerID;
+    this.count = count;
+    this.nodes = nodes;
+  };
+
+  HashArrayMapNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+    if (keyHash === undefined) {
+      keyHash = hash(key);
+    }
+    var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+    var node = this.nodes[idx];
+    return node
+      ? node.get(shift + SHIFT, keyHash, key, notSetValue)
+      : notSetValue;
+  };
+
+  HashArrayMapNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+    if (keyHash === undefined) {
+      keyHash = hash(key);
+    }
+    var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+    var removed = value === NOT_SET;
+    var nodes = this.nodes;
+    var node = nodes[idx];
+
+    if (removed && !node) {
+      return this;
+    }
+
+    var newNode = updateNode(
+      node,
+      ownerID,
+      shift + SHIFT,
+      keyHash,
+      key,
+      value,
+      didChangeSize,
+      didAlter
+    );
+    if (newNode === node) {
+      return this;
+    }
+
+    var newCount = this.count;
+    if (!node) {
+      newCount++;
+    } else if (!newNode) {
+      newCount--;
+      if (newCount < MIN_HASH_ARRAY_MAP_SIZE) {
+        return packNodes(ownerID, nodes, newCount, idx);
+      }
+    }
+
+    var isEditable = ownerID && ownerID === this.ownerID;
+    var newNodes = setAt(nodes, idx, newNode, isEditable);
+
+    if (isEditable) {
+      this.count = newCount;
+      this.nodes = newNodes;
+      return this;
+    }
+
+    return new HashArrayMapNode(ownerID, newCount, newNodes);
+  };
+
+  var HashCollisionNode = function HashCollisionNode(ownerID, keyHash, entries) {
+    this.ownerID = ownerID;
+    this.keyHash = keyHash;
+    this.entries = entries;
+  };
+
+  HashCollisionNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+    var entries = this.entries;
+    for (var ii = 0, len = entries.length; ii < len; ii++) {
+      if (is(key, entries[ii][0])) {
+        return entries[ii][1];
+      }
+    }
+    return notSetValue;
+  };
+
+  HashCollisionNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+    if (keyHash === undefined) {
+      keyHash = hash(key);
+    }
+
+    var removed = value === NOT_SET;
+
+    if (keyHash !== this.keyHash) {
+      if (removed) {
+        return this;
+      }
+      SetRef(didAlter);
+      SetRef(didChangeSize);
+      return mergeIntoNode(this, ownerID, shift, keyHash, [key, value]);
+    }
+
+    var entries = this.entries;
+    var idx = 0;
+    var len = entries.length;
+    for (; idx < len; idx++) {
+      if (is(key, entries[idx][0])) {
+        break;
+      }
+    }
+    var exists = idx < len;
+
+    if (exists ? entries[idx][1] === value : removed) {
+      return this;
+    }
+
+    SetRef(didAlter);
+    (removed || !exists) && SetRef(didChangeSize);
+
+    if (removed && len === 2) {
+      return new ValueNode(ownerID, this.keyHash, entries[idx ^ 1]);
+    }
+
+    var isEditable = ownerID && ownerID === this.ownerID;
+    var newEntries = isEditable ? entries : arrCopy(entries);
+
+    if (exists) {
+      if (removed) {
+        idx === len - 1
+          ? newEntries.pop()
+          : (newEntries[idx] = newEntries.pop());
+      } else {
+        newEntries[idx] = [key, value];
+      }
+    } else {
+      newEntries.push([key, value]);
+    }
+
+    if (isEditable) {
+      this.entries = newEntries;
+      return this;
+    }
+
+    return new HashCollisionNode(ownerID, this.keyHash, newEntries);
+  };
+
+  var ValueNode = function ValueNode(ownerID, keyHash, entry) {
+    this.ownerID = ownerID;
+    this.keyHash = keyHash;
+    this.entry = entry;
+  };
+
+  ValueNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+    return is(key, this.entry[0]) ? this.entry[1] : notSetValue;
+  };
+
+  ValueNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+    var removed = value === NOT_SET;
+    var keyMatch = is(key, this.entry[0]);
+    if (keyMatch ? value === this.entry[1] : removed) {
+      return this;
+    }
+
+    SetRef(didAlter);
+
+    if (removed) {
+      SetRef(didChangeSize);
+      return; // undefined
+    }
+
+    if (keyMatch) {
+      if (ownerID && ownerID === this.ownerID) {
+        this.entry[1] = value;
+        return this;
+      }
+      return new ValueNode(ownerID, this.keyHash, [key, value]);
+    }
+
+    SetRef(didChangeSize);
+    return mergeIntoNode(this, ownerID, shift, hash(key), [key, value]);
+  };
+
+  // #pragma Iterators
+
+  ArrayMapNode.prototype.iterate = HashCollisionNode.prototype.iterate =
+    function (fn, reverse) {
+      var entries = this.entries;
+      for (var ii = 0, maxIndex = entries.length - 1; ii <= maxIndex; ii++) {
+        if (fn(entries[reverse ? maxIndex - ii : ii]) === false) {
+          return false;
+        }
+      }
+    };
+
+  BitmapIndexedNode.prototype.iterate = HashArrayMapNode.prototype.iterate =
+    function (fn, reverse) {
+      var nodes = this.nodes;
+      for (var ii = 0, maxIndex = nodes.length - 1; ii <= maxIndex; ii++) {
+        var node = nodes[reverse ? maxIndex - ii : ii];
+        if (node && node.iterate(fn, reverse) === false) {
+          return false;
+        }
+      }
+    };
+
+  // eslint-disable-next-line @typescript-eslint/no-unused-vars
+  ValueNode.prototype.iterate = function (fn, reverse) {
+    return fn(this.entry);
+  };
+
+  var MapIterator = /*@__PURE__*/(function (Iterator) {
+    function MapIterator(map, type, reverse) {
+      this._type = type;
+      this._reverse = reverse;
+      this._stack = map._root && mapIteratorFrame(map._root);
+    }
+
+    if ( Iterator ) MapIterator.__proto__ = Iterator;
+    MapIterator.prototype = Object.create( Iterator && Iterator.prototype );
+    MapIterator.prototype.constructor = MapIterator;
+
+    MapIterator.prototype.next = function next () {
+      var type = this._type;
+      var stack = this._stack;
+      while (stack) {
+        var node = stack.node;
+        var index = stack.index++;
+        var maxIndex = (void 0);
+        if (node.entry) {
+          if (index === 0) {
+            return mapIteratorValue(type, node.entry);
+          }
+        } else if (node.entries) {
+          maxIndex = node.entries.length - 1;
+          if (index <= maxIndex) {
+            return mapIteratorValue(
+              type,
+              node.entries[this._reverse ? maxIndex - index : index]
+            );
+          }
+        } else {
+          maxIndex = node.nodes.length - 1;
+          if (index <= maxIndex) {
+            var subNode = node.nodes[this._reverse ? maxIndex - index : index];
+            if (subNode) {
+              if (subNode.entry) {
+                return mapIteratorValue(type, subNode.entry);
+              }
+              stack = this._stack = mapIteratorFrame(subNode, stack);
+            }
+            continue;
+          }
+        }
+        stack = this._stack = this._stack.__prev;
+      }
+      return iteratorDone();
+    };
+
+    return MapIterator;
+  }(Iterator));
+
+  function mapIteratorValue(type, entry) {
+    return iteratorValue(type, entry[0], entry[1]);
+  }
+
+  function mapIteratorFrame(node, prev) {
+    return {
+      node: node,
+      index: 0,
+      __prev: prev,
+    };
+  }
+
+  function makeMap(size, root, ownerID, hash) {
+    var map = Object.create(MapPrototype);
+    map.size = size;
+    map._root = root;
+    map.__ownerID = ownerID;
+    map.__hash = hash;
+    map.__altered = false;
+    return map;
+  }
+
+  var EMPTY_MAP;
+  function emptyMap() {
+    return EMPTY_MAP || (EMPTY_MAP = makeMap(0));
+  }
+
+  function updateMap(map, k, v) {
+    var newRoot;
+    var newSize;
+    if (!map._root) {
+      if (v === NOT_SET) {
+        return map;
+      }
+      newSize = 1;
+      newRoot = new ArrayMapNode(map.__ownerID, [[k, v]]);
+    } else {
+      var didChangeSize = MakeRef();
+      var didAlter = MakeRef();
+      newRoot = updateNode(
+        map._root,
+        map.__ownerID,
+        0,
+        undefined,
+        k,
+        v,
+        didChangeSize,
+        didAlter
+      );
+      if (!didAlter.value) {
+        return map;
+      }
+      newSize = map.size + (didChangeSize.value ? (v === NOT_SET ? -1 : 1) : 0);
+    }
+    if (map.__ownerID) {
+      map.size = newSize;
+      map._root = newRoot;
+      map.__hash = undefined;
+      map.__altered = true;
+      return map;
+    }
+    return newRoot ? makeMap(newSize, newRoot) : emptyMap();
+  }
+
+  function updateNode(
+    node,
+    ownerID,
+    shift,
+    keyHash,
+    key,
+    value,
+    didChangeSize,
+    didAlter
+  ) {
+    if (!node) {
+      if (value === NOT_SET) {
+        return node;
+      }
+      SetRef(didAlter);
+      SetRef(didChangeSize);
+      return new ValueNode(ownerID, keyHash, [key, value]);
+    }
+    return node.update(
+      ownerID,
+      shift,
+      keyHash,
+      key,
+      value,
+      didChangeSize,
+      didAlter
+    );
+  }
+
+  function isLeafNode(node) {
+    return (
+      node.constructor === ValueNode || node.constructor === HashCollisionNode
+    );
+  }
+
+  function mergeIntoNode(node, ownerID, shift, keyHash, entry) {
+    if (node.keyHash === keyHash) {
+      return new HashCollisionNode(ownerID, keyHash, [node.entry, entry]);
+    }
+
+    var idx1 = (shift === 0 ? node.keyHash : node.keyHash >>> shift) & MASK;
+    var idx2 = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+
+    var newNode;
+    var nodes =
+      idx1 === idx2
+        ? [mergeIntoNode(node, ownerID, shift + SHIFT, keyHash, entry)]
+        : ((newNode = new ValueNode(ownerID, keyHash, entry)),
+          idx1 < idx2 ? [node, newNode] : [newNode, node]);
+
+    return new BitmapIndexedNode(ownerID, (1 << idx1) | (1 << idx2), nodes);
+  }
+
+  function createNodes(ownerID, entries, key, value) {
+    if (!ownerID) {
+      ownerID = new OwnerID();
+    }
+    var node = new ValueNode(ownerID, hash(key), [key, value]);
+    for (var ii = 0; ii < entries.length; ii++) {
+      var entry = entries[ii];
+      node = node.update(ownerID, 0, undefined, entry[0], entry[1]);
+    }
+    return node;
+  }
+
+  function packNodes(ownerID, nodes, count, excluding) {
+    var bitmap = 0;
+    var packedII = 0;
+    var packedNodes = new Array(count);
+    for (var ii = 0, bit = 1, len = nodes.length; ii < len; ii++, bit <<= 1) {
+      var node = nodes[ii];
+      if (node !== undefined && ii !== excluding) {
+        bitmap |= bit;
+        packedNodes[packedII++] = node;
+      }
+    }
+    return new BitmapIndexedNode(ownerID, bitmap, packedNodes);
+  }
+
+  function expandNodes(ownerID, nodes, bitmap, including, node) {
+    var count = 0;
+    var expandedNodes = new Array(SIZE);
+    for (var ii = 0; bitmap !== 0; ii++, bitmap >>>= 1) {
+      expandedNodes[ii] = bitmap & 1 ? nodes[count++] : undefined;
+    }
+    expandedNodes[including] = node;
+    return new HashArrayMapNode(ownerID, count + 1, expandedNodes);
+  }
+
+  function popCount(x) {
+    x -= (x >> 1) & 0x55555555;
+    x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+    x = (x + (x >> 4)) & 0x0f0f0f0f;
+    x += x >> 8;
+    x += x >> 16;
+    return x & 0x7f;
+  }
+
+  function setAt(array, idx, val, canEdit) {
+    var newArray = canEdit ? array : arrCopy(array);
+    newArray[idx] = val;
+    return newArray;
+  }
+
+  function spliceIn(array, idx, val, canEdit) {
+    var newLen = array.length + 1;
+    if (canEdit && idx + 1 === newLen) {
+      array[idx] = val;
+      return array;
+    }
+    var newArray = new Array(newLen);
+    var after = 0;
+    for (var ii = 0; ii < newLen; ii++) {
+      if (ii === idx) {
+        newArray[ii] = val;
+        after = -1;
+      } else {
+        newArray[ii] = array[ii + after];
+      }
+    }
+    return newArray;
+  }
+
+  function spliceOut(array, idx, canEdit) {
+    var newLen = array.length - 1;
+    if (canEdit && idx === newLen) {
+      array.pop();
+      return array;
+    }
+    var newArray = new Array(newLen);
+    var after = 0;
+    for (var ii = 0; ii < newLen; ii++) {
+      if (ii === idx) {
+        after = 1;
+      }
+      newArray[ii] = array[ii + after];
+    }
+    return newArray;
+  }
+
+  var MAX_ARRAY_MAP_SIZE = SIZE / 4;
+  var MAX_BITMAP_INDEXED_SIZE = SIZE / 2;
+  var MIN_HASH_ARRAY_MAP_SIZE = SIZE / 4;
+
+  var IS_LIST_SYMBOL = '@@__IMMUTABLE_LIST__@@';
+
+  function isList(maybeList) {
+    return Boolean(maybeList && maybeList[IS_LIST_SYMBOL]);
+  }
+
+  var List = /*@__PURE__*/(function (IndexedCollection) {
+    function List(value) {
+      var empty = emptyList();
+      if (value === undefined || value === null) {
+        // eslint-disable-next-line no-constructor-return
+        return empty;
+      }
+      if (isList(value)) {
+        // eslint-disable-next-line no-constructor-return
+        return value;
+      }
+      var iter = IndexedCollection(value);
+      var size = iter.size;
+      if (size === 0) {
+        // eslint-disable-next-line no-constructor-return
+        return empty;
+      }
+      assertNotInfinite(size);
+      if (size > 0 && size < SIZE) {
+        // eslint-disable-next-line no-constructor-return
+        return makeList(0, size, SHIFT, null, new VNode(iter.toArray()));
+      }
+      // eslint-disable-next-line no-constructor-return
+      return empty.withMutations(function (list) {
+        list.setSize(size);
+        iter.forEach(function (v, i) { return list.set(i, v); });
+      });
+    }
+
+    if ( IndexedCollection ) List.__proto__ = IndexedCollection;
+    List.prototype = Object.create( IndexedCollection && IndexedCollection.prototype );
+    List.prototype.constructor = List;
+
+    List.of = function of (/*...values*/) {
+      return this(arguments);
+    };
+
+    List.prototype.toString = function toString () {
+      return this.__toString('List [', ']');
+    };
+
+    // @pragma Access
+
+    List.prototype.get = function get (index, notSetValue) {
+      index = wrapIndex(this, index);
+      if (index >= 0 && index < this.size) {
+        index += this._origin;
+        var node = listNodeFor(this, index);
+        return node && node.array[index & MASK];
+      }
+      return notSetValue;
+    };
+
+    // @pragma Modification
+
+    List.prototype.set = function set (index, value) {
+      return updateList(this, index, value);
+    };
+
+    List.prototype.remove = function remove (index) {
+      return !this.has(index)
+        ? this
+        : index === 0
+        ? this.shift()
+        : index === this.size - 1
+        ? this.pop()
+        : this.splice(index, 1);
+    };
+
+    List.prototype.insert = function insert (index, value) {
+      return this.splice(index, 0, value);
+    };
+
+    List.prototype.clear = function clear () {
+      if (this.size === 0) {
+        return this;
+      }
+      if (this.__ownerID) {
+        this.size = this._origin = this._capacity = 0;
+        this._level = SHIFT;
+        this._root = this._tail = this.__hash = undefined;
+        this.__altered = true;
+        return this;
+      }
+      return emptyList();
+    };
+
+    List.prototype.push = function push (/*...values*/) {
+      var values = arguments;
+      var oldSize = this.size;
+      return this.withMutations(function (list) {
+        setListBounds(list, 0, oldSize + values.length);
+        for (var ii = 0; ii < values.length; ii++) {
+          list.set(oldSize + ii, values[ii]);
+        }
+      });
+    };
+
+    List.prototype.pop = function pop () {
+      return setListBounds(this, 0, -1);
+    };
+
+    List.prototype.unshift = function unshift (/*...values*/) {
+      var values = arguments;
+      return this.withMutations(function (list) {
+        setListBounds(list, -values.length);
+        for (var ii = 0; ii < values.length; ii++) {
+          list.set(ii, values[ii]);
+        }
+      });
+    };
+
+    List.prototype.shift = function shift () {
+      return setListBounds(this, 1);
+    };
+
+    // @pragma Composition
+
+    List.prototype.concat = function concat (/*...collections*/) {
+      var arguments$1 = arguments;
+
+      var seqs = [];
+      for (var i = 0; i < arguments.length; i++) {
+        var argument = arguments$1[i];
+        var seq = IndexedCollection(
+          typeof argument !== 'string' && hasIterator(argument)
+            ? argument
+            : [argument]
+        );
+        if (seq.size !== 0) {
+          seqs.push(seq);
+        }
+      }
+      if (seqs.length === 0) {
+        return this;
+      }
+      if (this.size === 0 && !this.__ownerID && seqs.length === 1) {
+        return this.constructor(seqs[0]);
+      }
+      return this.withMutations(function (list) {
+        seqs.forEach(function (seq) { return seq.forEach(function (value) { return list.push(value); }); });
+      });
+    };
+
+    List.prototype.setSize = function setSize (size) {
+      return setListBounds(this, 0, size);
+    };
+
+    List.prototype.map = function map (mapper, context) {
+      var this$1$1 = this;
+
+      return this.withMutations(function (list) {
+        for (var i = 0; i < this$1$1.size; i++) {
+          list.set(i, mapper.call(context, list.get(i), i, this$1$1));
+        }
+      });
+    };
+
+    // @pragma Iteration
+
+    List.prototype.slice = function slice (begin, end) {
+      var size = this.size;
+      if (wholeSlice(begin, end, size)) {
+        return this;
+      }
+      return setListBounds(
+        this,
+        resolveBegin(begin, size),
+        resolveEnd(end, size)
+      );
+    };
+
+    List.prototype.__iterator = function __iterator (type, reverse) {
+      var index = reverse ? this.size : 0;
+      var values = iterateList(this, reverse);
+      return new Iterator(function () {
+        var value = values();
+        return value === DONE
+          ? iteratorDone()
+          : iteratorValue(type, reverse ? --index : index++, value);
+      });
+    };
+
+    List.prototype.__iterate = function __iterate (fn, reverse) {
+      var index = reverse ? this.size : 0;
+      var values = iterateList(this, reverse);
+      var value;
+      while ((value = values()) !== DONE) {
+        if (fn(value, reverse ? --index : index++, this) === false) {
+          break;
+        }
+      }
+      return index;
+    };
+
+    List.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+      if (ownerID === this.__ownerID) {
+        return this;
+      }
+      if (!ownerID) {
+        if (this.size === 0) {
+          return emptyList();
+        }
+        this.__ownerID = ownerID;
+        this.__altered = false;
+        return this;
+      }
+      return makeList(
+        this._origin,
+        this._capacity,
+        this._level,
+        this._root,
+        this._tail,
+        ownerID,
+        this.__hash
+      );
+    };
+
+    return List;
+  }(IndexedCollection));
+
+  List.isList = isList;
+
+  var ListPrototype = List.prototype;
+  ListPrototype[IS_LIST_SYMBOL] = true;
+  ListPrototype[DELETE] = ListPrototype.remove;
+  ListPrototype.merge = ListPrototype.concat;
+  ListPrototype.setIn = setIn;
+  ListPrototype.deleteIn = ListPrototype.removeIn = deleteIn;
+  ListPrototype.update = update;
+  ListPrototype.updateIn = updateIn;
+  ListPrototype.mergeIn = mergeIn;
+  ListPrototype.mergeDeepIn = mergeDeepIn;
+  ListPrototype.withMutations = withMutations;
+  ListPrototype.wasAltered = wasAltered;
+  ListPrototype.asImmutable = asImmutable;
+  ListPrototype['@@transducer/init'] = ListPrototype.asMutable = asMutable;
+  ListPrototype['@@transducer/step'] = function (result, arr) {
+    return result.push(arr);
+  };
+  ListPrototype['@@transducer/result'] = function (obj) {
+    return obj.asImmutable();
+  };
+
+  var VNode = function VNode(array, ownerID) {
+    this.array = array;
+    this.ownerID = ownerID;
+  };
+
+  // TODO: seems like these methods are very similar
+
+  VNode.prototype.removeBefore = function removeBefore (ownerID, level, index) {
+    if (
+      (index & ((1 << (level + SHIFT)) - 1)) === 0 ||
+      this.array.length === 0
+    ) {
+      return this;
+    }
+    var originIndex = (index >>> level) & MASK;
+    if (originIndex >= this.array.length) {
+      return new VNode([], ownerID);
+    }
+    var removingFirst = originIndex === 0;
+    var newChild;
+    if (level > 0) {
+      var oldChild = this.array[originIndex];
+      newChild =
+        oldChild && oldChild.removeBefore(ownerID, level - SHIFT, index);
+      if (newChild === oldChild && removingFirst) {
+        return this;
+      }
+    }
+    if (removingFirst && !newChild) {
+      return this;
+    }
+    var editable = editableVNode(this, ownerID);
+    if (!removingFirst) {
+      for (var ii = 0; ii < originIndex; ii++) {
+        editable.array[ii] = undefined;
+      }
+    }
+    if (newChild) {
+      editable.array[originIndex] = newChild;
+    }
+    return editable;
+  };
+
+  VNode.prototype.removeAfter = function removeAfter (ownerID, level, index) {
+    if (
+      index === (level ? 1 << (level + SHIFT) : SIZE) ||
+      this.array.length === 0
+    ) {
+      return this;
+    }
+    var sizeIndex = ((index - 1) >>> level) & MASK;
+    if (sizeIndex >= this.array.length) {
+      return this;
+    }
+
+    var newChild;
+    if (level > 0) {
+      var oldChild = this.array[sizeIndex];
+      newChild =
+        oldChild && oldChild.removeAfter(ownerID, level - SHIFT, index);
+      if (newChild === oldChild && sizeIndex === this.array.length - 1) {
+        return this;
+      }
+    }
+
+    var editable = editableVNode(this, ownerID);
+    editable.array.splice(sizeIndex + 1);
+    if (newChild) {
+      editable.array[sizeIndex] = newChild;
+    }
+    return editable;
+  };
+
+  var DONE = {};
+
+  function iterateList(list, reverse) {
+    var left = list._origin;
+    var right = list._capacity;
+    var tailPos = getTailOffset(right);
+    var tail = list._tail;
+
+    return iterateNodeOrLeaf(list._root, list._level, 0);
+
+    function iterateNodeOrLeaf(node, level, offset) {
+      return level === 0
+        ? iterateLeaf(node, offset)
+        : iterateNode(node, level, offset);
+    }
+
+    function iterateLeaf(node, offset) {
+      var array = offset === tailPos ? tail && tail.array : node && node.array;
+      var from = offset > left ? 0 : left - offset;
+      var to = right - offset;
+      if (to > SIZE) {
+        to = SIZE;
+      }
+      return function () {
+        if (from === to) {
+          return DONE;
+        }
+        var idx = reverse ? --to : from++;
+        return array && array[idx];
+      };
+    }
+
+    function iterateNode(node, level, offset) {
+      var values;
+      var array = node && node.array;
+      var from = offset > left ? 0 : (left - offset) >> level;
+      var to = ((right - offset) >> level) + 1;
+      if (to > SIZE) {
+        to = SIZE;
+      }
+      return function () {
+        while (true) {
+          if (values) {
+            var value = values();
+            if (value !== DONE) {
+              return value;
+            }
+            values = null;
+          }
+          if (from === to) {
+            return DONE;
+          }
+          var idx = reverse ? --to : from++;
+          values = iterateNodeOrLeaf(
+            array && array[idx],
+            level - SHIFT,
+            offset + (idx << level)
+          );
+        }
+      };
+    }
+  }
+
+  function makeList(origin, capacity, level, root, tail, ownerID, hash) {
+    var list = Object.create(ListPrototype);
+    list.size = capacity - origin;
+    list._origin = origin;
+    list._capacity = capacity;
+    list._level = level;
+    list._root = root;
+    list._tail = tail;
+    list.__ownerID = ownerID;
+    list.__hash = hash;
+    list.__altered = false;
+    return list;
+  }
+
+  function emptyList() {
+    return makeList(0, 0, SHIFT);
+  }
+
+  function updateList(list, index, value) {
+    index = wrapIndex(list, index);
+
+    if (index !== index) {
+      return list;
+    }
+
+    if (index >= list.size || index < 0) {
+      return list.withMutations(function (list) {
+        index < 0
+          ? setListBounds(list, index).set(0, value)
+          : setListBounds(list, 0, index + 1).set(index, value);
+      });
+    }
+
+    index += list._origin;
+
+    var newTail = list._tail;
+    var newRoot = list._root;
+    var didAlter = MakeRef();
+    if (index >= getTailOffset(list._capacity)) {
+      newTail = updateVNode(newTail, list.__ownerID, 0, index, value, didAlter);
+    } else {
+      newRoot = updateVNode(
+        newRoot,
+        list.__ownerID,
+        list._level,
+        index,
+        value,
+        didAlter
+      );
+    }
+
+    if (!didAlter.value) {
+      return list;
+    }
+
+    if (list.__ownerID) {
+      list._root = newRoot;
+      list._tail = newTail;
+      list.__hash = undefined;
+      list.__altered = true;
+      return list;
+    }
+    return makeList(list._origin, list._capacity, list._level, newRoot, newTail);
+  }
+
+  function updateVNode(node, ownerID, level, index, value, didAlter) {
+    var idx = (index >>> level) & MASK;
+    var nodeHas = node && idx < node.array.length;
+    if (!nodeHas && value === undefined) {
+      return node;
+    }
+
+    var newNode;
+
+    if (level > 0) {
+      var lowerNode = node && node.array[idx];
+      var newLowerNode = updateVNode(
+        lowerNode,
+        ownerID,
+        level - SHIFT,
+        index,
+        value,
+        didAlter
+      );
+      if (newLowerNode === lowerNode) {
+        return node;
+      }
+      newNode = editableVNode(node, ownerID);
+      newNode.array[idx] = newLowerNode;
+      return newNode;
+    }
+
+    if (nodeHas && node.array[idx] === value) {
+      return node;
+    }
+
+    if (didAlter) {
+      SetRef(didAlter);
+    }
+
+    newNode = editableVNode(node, ownerID);
+    if (value === undefined && idx === newNode.array.length - 1) {
+      newNode.array.pop();
+    } else {
+      newNode.array[idx] = value;
+    }
+    return newNode;
+  }
+
+  function editableVNode(node, ownerID) {
+    if (ownerID && node && ownerID === node.ownerID) {
+      return node;
+    }
+    return new VNode(node ? node.array.slice() : [], ownerID);
+  }
+
+  function listNodeFor(list, rawIndex) {
+    if (rawIndex >= getTailOffset(list._capacity)) {
+      return list._tail;
+    }
+    if (rawIndex < 1 << (list._level + SHIFT)) {
+      var node = list._root;
+      var level = list._level;
+      while (node && level > 0) {
+        node = node.array[(rawIndex >>> level) & MASK];
+        level -= SHIFT;
+      }
+      return node;
+    }
+  }
+
+  function setListBounds(list, begin, end) {
+    // Sanitize begin & end using this shorthand for ToInt32(argument)
+    // http://www.ecma-international.org/ecma-262/6.0/#sec-toint32
+    if (begin !== undefined) {
+      begin |= 0;
+    }
+    if (end !== undefined) {
+      end |= 0;
+    }
+    var owner = list.__ownerID || new OwnerID();
+    var oldOrigin = list._origin;
+    var oldCapacity = list._capacity;
+    var newOrigin = oldOrigin + begin;
+    var newCapacity =
+      end === undefined
+        ? oldCapacity
+        : end < 0
+        ? oldCapacity + end
+        : oldOrigin + end;
+    if (newOrigin === oldOrigin && newCapacity === oldCapacity) {
+      return list;
+    }
+
+    // If it's going to end after it starts, it's empty.
+    if (newOrigin >= newCapacity) {
+      return list.clear();
+    }
+
+    var newLevel = list._level;
+    var newRoot = list._root;
+
+    // New origin might need creating a higher root.
+    var offsetShift = 0;
+    while (newOrigin + offsetShift < 0) {
+      newRoot = new VNode(
+        newRoot && newRoot.array.length ? [undefined, newRoot] : [],
+        owner
+      );
+      newLevel += SHIFT;
+      offsetShift += 1 << newLevel;
+    }
+    if (offsetShift) {
+      newOrigin += offsetShift;
+      oldOrigin += offsetShift;
+      newCapacity += offsetShift;
+      oldCapacity += offsetShift;
+    }
+
+    var oldTailOffset = getTailOffset(oldCapacity);
+    var newTailOffset = getTailOffset(newCapacity);
+
+    // New size might need creating a higher root.
+    while (newTailOffset >= 1 << (newLevel + SHIFT)) {
+      newRoot = new VNode(
+        newRoot && newRoot.array.length ? [newRoot] : [],
+        owner
+      );
+      newLevel += SHIFT;
+    }
+
+    // Locate or create the new tail.
+    var oldTail = list._tail;
+    var newTail =
+      newTailOffset < oldTailOffset
+        ? listNodeFor(list, newCapacity - 1)
+        : newTailOffset > oldTailOffset
+        ? new VNode([], owner)
+        : oldTail;
+
+    // Merge Tail into tree.
+    if (
+      oldTail &&
+      newTailOffset > oldTailOffset &&
+      newOrigin < oldCapacity &&
+      oldTail.array.length
+    ) {
+      newRoot = editableVNode(newRoot, owner);
+      var node = newRoot;
+      for (var level = newLevel; level > SHIFT; level -= SHIFT) {
+        var idx = (oldTailOffset >>> level) & MASK;
+        node = node.array[idx] = editableVNode(node.array[idx], owner);
+      }
+      node.array[(oldTailOffset >>> SHIFT) & MASK] = oldTail;
+    }
+
+    // If the size has been reduced, there's a chance the tail needs to be trimmed.
+    if (newCapacity < oldCapacity) {
+      newTail = newTail && newTail.removeAfter(owner, 0, newCapacity);
+    }
+
+    // If the new origin is within the tail, then we do not need a root.
+    if (newOrigin >= newTailOffset) {
+      newOrigin -= newTailOffset;
+      newCapacity -= newTailOffset;
+      newLevel = SHIFT;
+      newRoot = null;
+      newTail = newTail && newTail.removeBefore(owner, 0, newOrigin);
+
+      // Otherwise, if the root has been trimmed, garbage collect.
+    } else if (newOrigin > oldOrigin || newTailOffset < oldTailOffset) {
+      offsetShift = 0;
+
+      // Identify the new top root node of the subtree of the old root.
+      while (newRoot) {
+        var beginIndex = (newOrigin >>> newLevel) & MASK;
+        if ((beginIndex !== newTailOffset >>> newLevel) & MASK) {
+          break;
+        }
+        if (beginIndex) {
+          offsetShift += (1 << newLevel) * beginIndex;
+        }
+        newLevel -= SHIFT;
+        newRoot = newRoot.array[beginIndex];
+      }
+
+      // Trim the new sides of the new root.
+      if (newRoot && newOrigin > oldOrigin) {
+        newRoot = newRoot.removeBefore(owner, newLevel, newOrigin - offsetShift);
+      }
+      if (newRoot && newTailOffset < oldTailOffset) {
+        newRoot = newRoot.removeAfter(
+          owner,
+          newLevel,
+          newTailOffset - offsetShift
+        );
+      }
+      if (offsetShift) {
+        newOrigin -= offsetShift;
+        newCapacity -= offsetShift;
+      }
+    }
+
+    if (list.__ownerID) {
+      list.size = newCapacity - newOrigin;
+      list._origin = newOrigin;
+      list._capacity = newCapacity;
+      list._level = newLevel;
+      list._root = newRoot;
+      list._tail = newTail;
+      list.__hash = undefined;
+      list.__altered = true;
+      return list;
+    }
+    return makeList(newOrigin, newCapacity, newLevel, newRoot, newTail);
+  }
+
+  function getTailOffset(size) {
+    return size < SIZE ? 0 : ((size - 1) >>> SHIFT) << SHIFT;
+  }
+
+  var OrderedMap = /*@__PURE__*/(function (Map) {
+    function OrderedMap(value) {
+      // eslint-disable-next-line no-constructor-return
+      return value === undefined || value === null
+        ? emptyOrderedMap()
+        : isOrderedMap(value)
+        ? value
+        : emptyOrderedMap().withMutations(function (map) {
+            var iter = KeyedCollection(value);
+            assertNotInfinite(iter.size);
+            iter.forEach(function (v, k) { return map.set(k, v); });
+          });
+    }
+
+    if ( Map ) OrderedMap.__proto__ = Map;
+    OrderedMap.prototype = Object.create( Map && Map.prototype );
+    OrderedMap.prototype.constructor = OrderedMap;
+
+    OrderedMap.of = function of (/*...values*/) {
+      return this(arguments);
+    };
+
+    OrderedMap.prototype.toString = function toString () {
+      return this.__toString('OrderedMap {', '}');
+    };
+
+    // @pragma Access
+
+    OrderedMap.prototype.get = function get (k, notSetValue) {
+      var index = this._map.get(k);
+      return index !== undefined ? this._list.get(index)[1] : notSetValue;
+    };
+
+    // @pragma Modification
+
+    OrderedMap.prototype.clear = function clear () {
+      if (this.size === 0) {
+        return this;
+      }
+      if (this.__ownerID) {
+        this.size = 0;
+        this._map.clear();
+        this._list.clear();
+        this.__altered = true;
+        return this;
+      }
+      return emptyOrderedMap();
+    };
+
+    OrderedMap.prototype.set = function set (k, v) {
+      return updateOrderedMap(this, k, v);
+    };
+
+    OrderedMap.prototype.remove = function remove (k) {
+      return updateOrderedMap(this, k, NOT_SET);
+    };
+
+    OrderedMap.prototype.__iterate = function __iterate (fn, reverse) {
+      var this$1$1 = this;
+
+      return this._list.__iterate(
+        function (entry) { return entry && fn(entry[1], entry[0], this$1$1); },
+        reverse
+      );
+    };
+
+    OrderedMap.prototype.__iterator = function __iterator (type, reverse) {
+      return this._list.fromEntrySeq().__iterator(type, reverse);
+    };
+
+    OrderedMap.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+      if (ownerID === this.__ownerID) {
+        return this;
+      }
+      var newMap = this._map.__ensureOwner(ownerID);
+      var newList = this._list.__ensureOwner(ownerID);
+      if (!ownerID) {
+        if (this.size === 0) {
+          return emptyOrderedMap();
+        }
+        this.__ownerID = ownerID;
+        this.__altered = false;
+        this._map = newMap;
+        this._list = newList;
+        return this;
+      }
+      return makeOrderedMap(newMap, newList, ownerID, this.__hash);
+    };
+
+    return OrderedMap;
+  }(Map));
+
+  OrderedMap.isOrderedMap = isOrderedMap;
+
+  OrderedMap.prototype[IS_ORDERED_SYMBOL] = true;
+  OrderedMap.prototype[DELETE] = OrderedMap.prototype.remove;
+
+  function makeOrderedMap(map, list, ownerID, hash) {
+    var omap = Object.create(OrderedMap.prototype);
+    omap.size = map ? map.size : 0;
+    omap._map = map;
+    omap._list = list;
+    omap.__ownerID = ownerID;
+    omap.__hash = hash;
+    omap.__altered = false;
+    return omap;
+  }
+
+  var EMPTY_ORDERED_MAP;
+  function emptyOrderedMap() {
+    return (
+      EMPTY_ORDERED_MAP ||
+      (EMPTY_ORDERED_MAP = makeOrderedMap(emptyMap(), emptyList()))
+    );
+  }
+
+  function updateOrderedMap(omap, k, v) {
+    var map = omap._map;
+    var list = omap._list;
+    var i = map.get(k);
+    var has = i !== undefined;
+    var newMap;
+    var newList;
+    if (v === NOT_SET) {
+      // removed
+      if (!has) {
+        return omap;
+      }
+      if (list.size >= SIZE && list.size >= map.size * 2) {
+        newList = list.filter(function (entry, idx) { return entry !== undefined && i !== idx; });
+        newMap = newList
+          .toKeyedSeq()
+          .map(function (entry) { return entry[0]; })
+          .flip()
+          .toMap();
+        if (omap.__ownerID) {
+          newMap.__ownerID = newList.__ownerID = omap.__ownerID;
+        }
+      } else {
+        newMap = map.remove(k);
+        newList = i === list.size - 1 ? list.pop() : list.set(i, undefined);
+      }
+    } else if (has) {
+      if (v === list.get(i)[1]) {
+        return omap;
+      }
+      newMap = map;
+      newList = list.set(i, [k, v]);
+    } else {
+      newMap = map.set(k, list.size);
+      newList = list.set(list.size, [k, v]);
+    }
+    if (omap.__ownerID) {
+      omap.size = newMap.size;
+      omap._map = newMap;
+      omap._list = newList;
+      omap.__hash = undefined;
+      omap.__altered = true;
+      return omap;
+    }
+    return makeOrderedMap(newMap, newList);
+  }
+
+  var IS_STACK_SYMBOL = '@@__IMMUTABLE_STACK__@@';
+
+  function isStack(maybeStack) {
+    return Boolean(maybeStack && maybeStack[IS_STACK_SYMBOL]);
+  }
+
+  var Stack = /*@__PURE__*/(function (IndexedCollection) {
+    function Stack(value) {
+      // eslint-disable-next-line no-constructor-return
+      return value === undefined || value === null
+        ? emptyStack()
+        : isStack(value)
+        ? value
+        : emptyStack().pushAll(value);
+    }
+
+    if ( IndexedCollection ) Stack.__proto__ = IndexedCollection;
+    Stack.prototype = Object.create( IndexedCollection && IndexedCollection.prototype );
+    Stack.prototype.constructor = Stack;
+
+    Stack.of = function of (/*...values*/) {
+      return this(arguments);
+    };
+
+    Stack.prototype.toString = function toString () {
+      return this.__toString('Stack [', ']');
+    };
+
+    // @pragma Access
+
+    Stack.prototype.get = function get (index, notSetValue) {
+      var head = this._head;
+      index = wrapIndex(this, index);
+      while (head && index--) {
+        head = head.next;
+      }
+      return head ? head.value : notSetValue;
+    };
+
+    Stack.prototype.peek = function peek () {
+      return this._head && this._head.value;
+    };
+
+    // @pragma Modification
+
+    Stack.prototype.push = function push (/*...values*/) {
+      var arguments$1 = arguments;
+
+      if (arguments.length === 0) {
+        return this;
+      }
+      var newSize = this.size + arguments.length;
+      var head = this._head;
+      for (var ii = arguments.length - 1; ii >= 0; ii--) {
+        head = {
+          value: arguments$1[ii],
+          next: head,
+        };
+      }
+      if (this.__ownerID) {
+        this.size = newSize;
+        this._head = head;
+        this.__hash = undefined;
+        this.__altered = true;
+        return this;
+      }
+      return makeStack(newSize, head);
+    };
+
+    Stack.prototype.pushAll = function pushAll (iter) {
+      iter = IndexedCollection(iter);
+      if (iter.size === 0) {
+        return this;
+      }
+      if (this.size === 0 && isStack(iter)) {
+        return iter;
+      }
+      assertNotInfinite(iter.size);
+      var newSize = this.size;
+      var head = this._head;
+      iter.__iterate(function (value) {
+        newSize++;
+        head = {
+          value: value,
+          next: head,
+        };
+      }, /* reverse */ true);
+      if (this.__ownerID) {
+        this.size = newSize;
+        this._head = head;
+        this.__hash = undefined;
+        this.__altered = true;
+        return this;
+      }
+      return makeStack(newSize, head);
+    };
+
+    Stack.prototype.pop = function pop () {
+      return this.slice(1);
+    };
+
+    Stack.prototype.clear = function clear () {
+      if (this.size === 0) {
+        return this;
+      }
+      if (this.__ownerID) {
+        this.size = 0;
+        this._head = undefined;
+        this.__hash = undefined;
+        this.__altered = true;
+        return this;
+      }
+      return emptyStack();
+    };
+
+    Stack.prototype.slice = function slice (begin, end) {
+      if (wholeSlice(begin, end, this.size)) {
+        return this;
+      }
+      var resolvedBegin = resolveBegin(begin, this.size);
+      var resolvedEnd = resolveEnd(end, this.size);
+      if (resolvedEnd !== this.size) {
+        // super.slice(begin, end);
+        return IndexedCollection.prototype.slice.call(this, begin, end);
+      }
+      var newSize = this.size - resolvedBegin;
+      var head = this._head;
+      while (resolvedBegin--) {
+        head = head.next;
+      }
+      if (this.__ownerID) {
+        this.size = newSize;
+        this._head = head;
+        this.__hash = undefined;
+        this.__altered = true;
+        return this;
+      }
+      return makeStack(newSize, head);
+    };
+
+    // @pragma Mutability
+
+    Stack.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+      if (ownerID === this.__ownerID) {
+        return this;
+      }
+      if (!ownerID) {
+        if (this.size === 0) {
+          return emptyStack();
+        }
+        this.__ownerID = ownerID;
+        this.__altered = false;
+        return this;
+      }
+      return makeStack(this.size, this._head, ownerID, this.__hash);
+    };
+
+    // @pragma Iteration
+
+    Stack.prototype.__iterate = function __iterate (fn, reverse) {
+      var this$1$1 = this;
+
+      if (reverse) {
+        return new ArraySeq(this.toArray()).__iterate(
+          function (v, k) { return fn(v, k, this$1$1); },
+          reverse
+        );
+      }
+      var iterations = 0;
+      var node = this._head;
+      while (node) {
+        if (fn(node.value, iterations++, this) === false) {
+          break;
+        }
+        node = node.next;
+      }
+      return iterations;
+    };
+
+    Stack.prototype.__iterator = function __iterator (type, reverse) {
+      if (reverse) {
+        return new ArraySeq(this.toArray()).__iterator(type, reverse);
+      }
+      var iterations = 0;
+      var node = this._head;
+      return new Iterator(function () {
+        if (node) {
+          var value = node.value;
+          node = node.next;
+          return iteratorValue(type, iterations++, value);
+        }
+        return iteratorDone();
+      });
+    };
+
+    return Stack;
+  }(IndexedCollection));
+
+  Stack.isStack = isStack;
+
+  var StackPrototype = Stack.prototype;
+  StackPrototype[IS_STACK_SYMBOL] = true;
+  StackPrototype.shift = StackPrototype.pop;
+  StackPrototype.unshift = StackPrototype.push;
+  StackPrototype.unshiftAll = StackPrototype.pushAll;
+  StackPrototype.withMutations = withMutations;
+  StackPrototype.wasAltered = wasAltered;
+  StackPrototype.asImmutable = asImmutable;
+  StackPrototype['@@transducer/init'] = StackPrototype.asMutable = asMutable;
+  StackPrototype['@@transducer/step'] = function (result, arr) {
+    return result.unshift(arr);
+  };
+  StackPrototype['@@transducer/result'] = function (obj) {
+    return obj.asImmutable();
+  };
+
+  function makeStack(size, head, ownerID, hash) {
+    var map = Object.create(StackPrototype);
+    map.size = size;
+    map._head = head;
+    map.__ownerID = ownerID;
+    map.__hash = hash;
+    map.__altered = false;
+    return map;
+  }
+
+  var EMPTY_STACK;
+  function emptyStack() {
+    return EMPTY_STACK || (EMPTY_STACK = makeStack(0));
+  }
+
+  var IS_SET_SYMBOL = '@@__IMMUTABLE_SET__@@';
+
+  function isSet(maybeSet) {
+    return Boolean(maybeSet && maybeSet[IS_SET_SYMBOL]);
+  }
+
+  function isOrderedSet(maybeOrderedSet) {
+    return isSet(maybeOrderedSet) && isOrdered(maybeOrderedSet);
+  }
+
+  function deepEqual(a, b) {
+    if (a === b) {
+      return true;
+    }
+
+    if (
+      !isCollection(b) ||
+      (a.size !== undefined && b.size !== undefined && a.size !== b.size) ||
+      (a.__hash !== undefined &&
+        b.__hash !== undefined &&
+        a.__hash !== b.__hash) ||
+      isKeyed(a) !== isKeyed(b) ||
+      isIndexed(a) !== isIndexed(b) ||
+      isOrdered(a) !== isOrdered(b)
+    ) {
+      return false;
+    }
+
+    if (a.size === 0 && b.size === 0) {
+      return true;
+    }
+
+    var notAssociative = !isAssociative(a);
+
+    if (isOrdered(a)) {
+      var entries = a.entries();
+      return (
+        b.every(function (v, k) {
+          var entry = entries.next().value;
+          return entry && is(entry[1], v) && (notAssociative || is(entry[0], k));
+        }) && entries.next().done
+      );
+    }
+
+    var flipped = false;
+
+    if (a.size === undefined) {
+      if (b.size === undefined) {
+        if (typeof a.cacheResult === 'function') {
+          a.cacheResult();
+        }
+      } else {
+        flipped = true;
+        var _ = a;
+        a = b;
+        b = _;
+      }
+    }
+
+    var allEqual = true;
+    var bSize = b.__iterate(function (v, k) {
+      if (
+        notAssociative
+          ? !a.has(v)
+          : flipped
+          ? !is(v, a.get(k, NOT_SET))
+          : !is(a.get(k, NOT_SET), v)
+      ) {
+        allEqual = false;
+        return false;
+      }
+    });
+
+    return allEqual && a.size === bSize;
+  }
+
+  /**
+   * Contributes additional methods to a constructor
+   */
+  function mixin(ctor, methods) {
+    var keyCopier = function (key) {
+      ctor.prototype[key] = methods[key];
+    };
+    Object.keys(methods).forEach(keyCopier);
+    Object.getOwnPropertySymbols &&
+      Object.getOwnPropertySymbols(methods).forEach(keyCopier);
+    return ctor;
+  }
+
+  function toJS(value) {
+    if (!value || typeof value !== 'object') {
+      return value;
+    }
+    if (!isCollection(value)) {
+      if (!isDataStructure(value)) {
+        return value;
+      }
+      value = Seq(value);
+    }
+    if (isKeyed(value)) {
+      var result$1 = {};
+      value.__iterate(function (v, k) {
+        result$1[k] = toJS(v);
+      });
+      return result$1;
+    }
+    var result = [];
+    value.__iterate(function (v) {
+      result.push(toJS(v));
+    });
+    return result;
+  }
+
+  var Set = /*@__PURE__*/(function (SetCollection) {
+    function Set(value) {
+      // eslint-disable-next-line no-constructor-return
+      return value === undefined || value === null
+        ? emptySet()
+        : isSet(value) && !isOrdered(value)
+        ? value
+        : emptySet().withMutations(function (set) {
+            var iter = SetCollection(value);
+            assertNotInfinite(iter.size);
+            iter.forEach(function (v) { return set.add(v); });
+          });
+    }
+
+    if ( SetCollection ) Set.__proto__ = SetCollection;
+    Set.prototype = Object.create( SetCollection && SetCollection.prototype );
+    Set.prototype.constructor = Set;
+
+    Set.of = function of (/*...values*/) {
+      return this(arguments);
+    };
+
+    Set.fromKeys = function fromKeys (value) {
+      return this(KeyedCollection(value).keySeq());
+    };
+
+    Set.intersect = function intersect (sets) {
+      sets = Collection(sets).toArray();
+      return sets.length
+        ? SetPrototype.intersect.apply(Set(sets.pop()), sets)
+        : emptySet();
+    };
+
+    Set.union = function union (sets) {
+      sets = Collection(sets).toArray();
+      return sets.length
+        ? SetPrototype.union.apply(Set(sets.pop()), sets)
+        : emptySet();
+    };
+
+    Set.prototype.toString = function toString () {
+      return this.__toString('Set {', '}');
+    };
+
+    // @pragma Access
+
+    Set.prototype.has = function has (value) {
+      return this._map.has(value);
+    };
+
+    // @pragma Modification
+
+    Set.prototype.add = function add (value) {
+      return updateSet(this, this._map.set(value, value));
+    };
+
+    Set.prototype.remove = function remove (value) {
+      return updateSet(this, this._map.remove(value));
+    };
+
+    Set.prototype.clear = function clear () {
+      return updateSet(this, this._map.clear());
+    };
+
+    // @pragma Composition
+
+    Set.prototype.map = function map (mapper, context) {
+      var this$1$1 = this;
+
+      // keep track if the set is altered by the map function
+      var didChanges = false;
+
+      var newMap = updateSet(
+        this,
+        this._map.mapEntries(function (ref) {
+          var v = ref[1];
+
+          var mapped = mapper.call(context, v, v, this$1$1);
+
+          if (mapped !== v) {
+            didChanges = true;
+          }
+
+          return [mapped, mapped];
+        }, context)
+      );
+
+      return didChanges ? newMap : this;
+    };
+
+    Set.prototype.union = function union () {
+      var iters = [], len = arguments.length;
+      while ( len-- ) iters[ len ] = arguments[ len ];
+
+      iters = iters.filter(function (x) { return x.size !== 0; });
+      if (iters.length === 0) {
+        return this;
+      }
+      if (this.size === 0 && !this.__ownerID && iters.length === 1) {
+        return this.constructor(iters[0]);
+      }
+      return this.withMutations(function (set) {
+        for (var ii = 0; ii < iters.length; ii++) {
+          if (typeof iters[ii] === 'string') {
+            set.add(iters[ii]);
+          } else {
+            SetCollection(iters[ii]).forEach(function (value) { return set.add(value); });
+          }
+        }
+      });
+    };
+
+    Set.prototype.intersect = function intersect () {
+      var iters = [], len = arguments.length;
+      while ( len-- ) iters[ len ] = arguments[ len ];
+
+      if (iters.length === 0) {
+        return this;
+      }
+      iters = iters.map(function (iter) { return SetCollection(iter); });
+      var toRemove = [];
+      this.forEach(function (value) {
+        if (!iters.every(function (iter) { return iter.includes(value); })) {
+          toRemove.push(value);
+        }
+      });
+      return this.withMutations(function (set) {
+        toRemove.forEach(function (value) {
+          set.remove(value);
+        });
+      });
+    };
+
+    Set.prototype.subtract = function subtract () {
+      var iters = [], len = arguments.length;
+      while ( len-- ) iters[ len ] = arguments[ len ];
+
+      if (iters.length === 0) {
+        return this;
+      }
+      iters = iters.map(function (iter) { return SetCollection(iter); });
+      var toRemove = [];
+      this.forEach(function (value) {
+        if (iters.some(function (iter) { return iter.includes(value); })) {
+          toRemove.push(value);
+        }
+      });
+      return this.withMutations(function (set) {
+        toRemove.forEach(function (value) {
+          set.remove(value);
+        });
+      });
+    };
+
+    Set.prototype.sort = function sort (comparator) {
+      // Late binding
+      return OrderedSet(sortFactory(this, comparator));
+    };
+
+    Set.prototype.sortBy = function sortBy (mapper, comparator) {
+      // Late binding
+      return OrderedSet(sortFactory(this, comparator, mapper));
+    };
+
+    Set.prototype.wasAltered = function wasAltered () {
+      return this._map.wasAltered();
+    };
+
+    Set.prototype.__iterate = function __iterate (fn, reverse) {
+      var this$1$1 = this;
+
+      return this._map.__iterate(function (k) { return fn(k, k, this$1$1); }, reverse);
+    };
+
+    Set.prototype.__iterator = function __iterator (type, reverse) {
+      return this._map.__iterator(type, reverse);
+    };
+
+    Set.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+      if (ownerID === this.__ownerID) {
+        return this;
+      }
+      var newMap = this._map.__ensureOwner(ownerID);
+      if (!ownerID) {
+        if (this.size === 0) {
+          return this.__empty();
+        }
+        this.__ownerID = ownerID;
+        this._map = newMap;
+        return this;
+      }
+      return this.__make(newMap, ownerID);
+    };
+
+    return Set;
+  }(SetCollection));
+
+  Set.isSet = isSet;
+
+  var SetPrototype = Set.prototype;
+  SetPrototype[IS_SET_SYMBOL] = true;
+  SetPrototype[DELETE] = SetPrototype.remove;
+  SetPrototype.merge = SetPrototype.concat = SetPrototype.union;
+  SetPrototype.withMutations = withMutations;
+  SetPrototype.asImmutable = asImmutable;
+  SetPrototype['@@transducer/init'] = SetPrototype.asMutable = asMutable;
+  SetPrototype['@@transducer/step'] = function (result, arr) {
+    return result.add(arr);
+  };
+  SetPrototype['@@transducer/result'] = function (obj) {
+    return obj.asImmutable();
+  };
+
+  SetPrototype.__empty = emptySet;
+  SetPrototype.__make = makeSet;
+
+  function updateSet(set, newMap) {
+    if (set.__ownerID) {
+      set.size = newMap.size;
+      set._map = newMap;
+      return set;
+    }
+    return newMap === set._map
+      ? set
+      : newMap.size === 0
+      ? set.__empty()
+      : set.__make(newMap);
+  }
+
+  function makeSet(map, ownerID) {
+    var set = Object.create(SetPrototype);
+    set.size = map ? map.size : 0;
+    set._map = map;
+    set.__ownerID = ownerID;
+    return set;
+  }
+
+  var EMPTY_SET;
+  function emptySet() {
+    return EMPTY_SET || (EMPTY_SET = makeSet(emptyMap()));
+  }
+
+  /**
+   * Returns a lazy seq of nums from start (inclusive) to end
+   * (exclusive), by step, where start defaults to 0, step to 1, and end to
+   * infinity. When start is equal to end, returns empty list.
+   */
+  var Range = /*@__PURE__*/(function (IndexedSeq) {
+    function Range(start, end, step) {
+      if ( step === void 0 ) step = 1;
+
+      if (!(this instanceof Range)) {
+        // eslint-disable-next-line no-constructor-return
+        return new Range(start, end, step);
+      }
+      invariant(step !== 0, 'Cannot step a Range by 0');
+      invariant(
+        start !== undefined,
+        'You must define a start value when using Range'
+      );
+      invariant(
+        end !== undefined,
+        'You must define an end value when using Range'
+      );
+
+      step = Math.abs(step);
+      if (end < start) {
+        step = -step;
+      }
+      this._start = start;
+      this._end = end;
+      this._step = step;
+      this.size = Math.max(0, Math.ceil((end - start) / step - 1) + 1);
+      if (this.size === 0) {
+        if (EMPTY_RANGE) {
+          // eslint-disable-next-line no-constructor-return
+          return EMPTY_RANGE;
+        }
+        // eslint-disable-next-line @typescript-eslint/no-this-alias
+        EMPTY_RANGE = this;
+      }
+    }
+
+    if ( IndexedSeq ) Range.__proto__ = IndexedSeq;
+    Range.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+    Range.prototype.constructor = Range;
+
+    Range.prototype.toString = function toString () {
+      if (this.size === 0) {
+        return 'Range []';
+      }
+      return (
+        'Range [ ' +
+        this._start +
+        '...' +
+        this._end +
+        (this._step !== 1 ? ' by ' + this._step : '') +
+        ' ]'
+      );
+    };
+
+    Range.prototype.get = function get (index, notSetValue) {
+      return this.has(index)
+        ? this._start + wrapIndex(this, index) * this._step
+        : notSetValue;
+    };
+
+    Range.prototype.includes = function includes (searchValue) {
+      var possibleIndex = (searchValue - this._start) / this._step;
+      return (
+        possibleIndex >= 0 &&
+        possibleIndex < this.size &&
+        possibleIndex === Math.floor(possibleIndex)
+      );
+    };
+
+    Range.prototype.slice = function slice (begin, end) {
+      if (wholeSlice(begin, end, this.size)) {
+        return this;
+      }
+      begin = resolveBegin(begin, this.size);
+      end = resolveEnd(end, this.size);
+      if (end <= begin) {
+        return new Range(0, 0);
+      }
+      return new Range(
+        this.get(begin, this._end),
+        this.get(end, this._end),
+        this._step
+      );
+    };
+
+    Range.prototype.indexOf = function indexOf (searchValue) {
+      var offsetValue = searchValue - this._start;
+      if (offsetValue % this._step === 0) {
+        var index = offsetValue / this._step;
+        if (index >= 0 && index < this.size) {
+          return index;
+        }
+      }
+      return -1;
+    };
+
+    Range.prototype.lastIndexOf = function lastIndexOf (searchValue) {
+      return this.indexOf(searchValue);
+    };
+
+    Range.prototype.__iterate = function __iterate (fn, reverse) {
+      var size = this.size;
+      var step = this._step;
+      var value = reverse ? this._start + (size - 1) * step : this._start;
+      var i = 0;
+      while (i !== size) {
+        if (fn(value, reverse ? size - ++i : i++, this) === false) {
+          break;
+        }
+        value += reverse ? -step : step;
+      }
+      return i;
+    };
+
+    Range.prototype.__iterator = function __iterator (type, reverse) {
+      var size = this.size;
+      var step = this._step;
+      var value = reverse ? this._start + (size - 1) * step : this._start;
+      var i = 0;
+      return new Iterator(function () {
+        if (i === size) {
+          return iteratorDone();
+        }
+        var v = value;
+        value += reverse ? -step : step;
+        return iteratorValue(type, reverse ? size - ++i : i++, v);
+      });
+    };
+
+    Range.prototype.equals = function equals (other) {
+      return other instanceof Range
+        ? this._start === other._start &&
+            this._end === other._end &&
+            this._step === other._step
+        : deepEqual(this, other);
+    };
+
+    return Range;
+  }(IndexedSeq));
+
+  var EMPTY_RANGE;
+
+  function getIn$1(collection, searchKeyPath, notSetValue) {
+    var keyPath = coerceKeyPath(searchKeyPath);
+    var i = 0;
+    while (i !== keyPath.length) {
+      collection = get(collection, keyPath[i++], NOT_SET);
+      if (collection === NOT_SET) {
+        return notSetValue;
+      }
+    }
+    return collection;
+  }
+
+  function getIn(searchKeyPath, notSetValue) {
+    return getIn$1(this, searchKeyPath, notSetValue);
+  }
+
+  function hasIn$1(collection, keyPath) {
+    return getIn$1(collection, keyPath, NOT_SET) !== NOT_SET;
+  }
+
+  function hasIn(searchKeyPath) {
+    return hasIn$1(this, searchKeyPath);
+  }
+
+  function toObject() {
+    assertNotInfinite(this.size);
+    var object = {};
+    this.__iterate(function (v, k) {
+      object[k] = v;
+    });
+    return object;
+  }
+
+  Collection.Iterator = Iterator;
+
+  mixin(Collection, {
+    // ### Conversion to other types
+
+    toArray: function toArray() {
+      assertNotInfinite(this.size);
+      var array = new Array(this.size || 0);
+      var useTuples = isKeyed(this);
+      var i = 0;
+      this.__iterate(function (v, k) {
+        // Keyed collections produce an array of tuples.
+        array[i++] = useTuples ? [k, v] : v;
+      });
+      return array;
+    },
+
+    toIndexedSeq: function toIndexedSeq() {
+      return new ToIndexedSequence(this);
+    },
+
+    toJS: function toJS$1() {
+      return toJS(this);
+    },
+
+    toKeyedSeq: function toKeyedSeq() {
+      return new ToKeyedSequence(this, true);
+    },
+
+    toMap: function toMap() {
+      // Use Late Binding here to solve the circular dependency.
+      return Map(this.toKeyedSeq());
+    },
+
+    toObject: toObject,
+
+    toOrderedMap: function toOrderedMap() {
+      // Use Late Binding here to solve the circular dependency.
+      return OrderedMap(this.toKeyedSeq());
+    },
+
+    toOrderedSet: function toOrderedSet() {
+      // Use Late Binding here to solve the circular dependency.
+      return OrderedSet(isKeyed(this) ? this.valueSeq() : this);
+    },
+
+    toSet: function toSet() {
+      // Use Late Binding here to solve the circular dependency.
+      return Set(isKeyed(this) ? this.valueSeq() : this);
+    },
+
+    toSetSeq: function toSetSeq() {
+      return new ToSetSequence(this);
+    },
+
+    toSeq: function toSeq() {
+      return isIndexed(this)
+        ? this.toIndexedSeq()
+        : isKeyed(this)
+        ? this.toKeyedSeq()
+        : this.toSetSeq();
+    },
+
+    toStack: function toStack() {
+      // Use Late Binding here to solve the circular dependency.
+      return Stack(isKeyed(this) ? this.valueSeq() : this);
+    },
+
+    toList: function toList() {
+      // Use Late Binding here to solve the circular dependency.
+      return List(isKeyed(this) ? this.valueSeq() : this);
+    },
+
+    // ### Common JavaScript methods and properties
+
+    toString: function toString() {
+      return '[Collection]';
+    },
+
+    __toString: function __toString(head, tail) {
+      if (this.size === 0) {
+        return head + tail;
+      }
+      return (
+        head +
+        ' ' +
+        this.toSeq().map(this.__toStringMapper).join(', ') +
+        ' ' +
+        tail
+      );
+    },
+
+    // ### ES6 Collection methods (ES6 Array and Map)
+
+    concat: function concat() {
+      var values = [], len = arguments.length;
+      while ( len-- ) values[ len ] = arguments[ len ];
+
+      return reify(this, concatFactory(this, values));
+    },
+
+    includes: function includes(searchValue) {
+      return this.some(function (value) { return is(value, searchValue); });
+    },
+
+    entries: function entries() {
+      return this.__iterator(ITERATE_ENTRIES);
+    },
+
+    every: function every(predicate, context) {
+      assertNotInfinite(this.size);
+      var returnValue = true;
+      this.__iterate(function (v, k, c) {
+        if (!predicate.call(context, v, k, c)) {
+          returnValue = false;
+          return false;
+        }
+      });
+      return returnValue;
+    },
+
+    filter: function filter(predicate, context) {
+      return reify(this, filterFactory(this, predicate, context, true));
+    },
+
+    partition: function partition(predicate, context) {
+      return partitionFactory(this, predicate, context);
+    },
+
+    find: function find(predicate, context, notSetValue) {
+      var entry = this.findEntry(predicate, context);
+      return entry ? entry[1] : notSetValue;
+    },
+
+    forEach: function forEach(sideEffect, context) {
+      assertNotInfinite(this.size);
+      return this.__iterate(context ? sideEffect.bind(context) : sideEffect);
+    },
+
+    join: function join(separator) {
+      assertNotInfinite(this.size);
+      separator = separator !== undefined ? '' + separator : ',';
+      var joined = '';
+      var isFirst = true;
+      this.__iterate(function (v) {
+        isFirst ? (isFirst = false) : (joined += separator);
+        joined += v !== null && v !== undefined ? v.toString() : '';
+      });
+      return joined;
+    },
+
+    keys: function keys() {
+      return this.__iterator(ITERATE_KEYS);
+    },
+
+    map: function map(mapper, context) {
+      return reify(this, mapFactory(this, mapper, context));
+    },
+
+    reduce: function reduce$1(reducer, initialReduction, context) {
+      return reduce(
+        this,
+        reducer,
+        initialReduction,
+        context,
+        arguments.length < 2,
+        false
+      );
+    },
+
+    reduceRight: function reduceRight(reducer, initialReduction, context) {
+      return reduce(
+        this,
+        reducer,
+        initialReduction,
+        context,
+        arguments.length < 2,
+        true
+      );
+    },
+
+    reverse: function reverse() {
+      return reify(this, reverseFactory(this, true));
+    },
+
+    slice: function slice(begin, end) {
+      return reify(this, sliceFactory(this, begin, end, true));
+    },
+
+    some: function some(predicate, context) {
+      assertNotInfinite(this.size);
+      var returnValue = false;
+      this.__iterate(function (v, k, c) {
+        if (predicate.call(context, v, k, c)) {
+          returnValue = true;
+          return false;
+        }
+      });
+      return returnValue;
+    },
+
+    sort: function sort(comparator) {
+      return reify(this, sortFactory(this, comparator));
+    },
+
+    values: function values() {
+      return this.__iterator(ITERATE_VALUES);
+    },
+
+    // ### More sequential methods
+
+    butLast: function butLast() {
+      return this.slice(0, -1);
+    },
+
+    isEmpty: function isEmpty() {
+      return this.size !== undefined ? this.size === 0 : !this.some(function () { return true; });
+    },
+
+    count: function count(predicate, context) {
+      return ensureSize(
+        predicate ? this.toSeq().filter(predicate, context) : this
+      );
+    },
+
+    countBy: function countBy(grouper, context) {
+      return countByFactory(this, grouper, context);
+    },
+
+    equals: function equals(other) {
+      return deepEqual(this, other);
+    },
+
+    entrySeq: function entrySeq() {
+      // eslint-disable-next-line @typescript-eslint/no-this-alias
+      var collection = this;
+      if (collection._cache) {
+        // We cache as an entries array, so we can just return the cache!
+        return new ArraySeq(collection._cache);
+      }
+      var entriesSequence = collection.toSeq().map(entryMapper).toIndexedSeq();
+      entriesSequence.fromEntrySeq = function () { return collection.toSeq(); };
+      return entriesSequence;
+    },
+
+    filterNot: function filterNot(predicate, context) {
+      return this.filter(not(predicate), context);
+    },
+
+    findEntry: function findEntry(predicate, context, notSetValue) {
+      var found = notSetValue;
+      this.__iterate(function (v, k, c) {
+        if (predicate.call(context, v, k, c)) {
+          found = [k, v];
+          return false;
+        }
+      });
+      return found;
+    },
+
+    findKey: function findKey(predicate, context) {
+      var entry = this.findEntry(predicate, context);
+      return entry && entry[0];
+    },
+
+    findLast: function findLast(predicate, context, notSetValue) {
+      return this.toKeyedSeq().reverse().find(predicate, context, notSetValue);
+    },
+
+    findLastEntry: function findLastEntry(predicate, context, notSetValue) {
+      return this.toKeyedSeq()
+        .reverse()
+        .findEntry(predicate, context, notSetValue);
+    },
+
+    findLastKey: function findLastKey(predicate, context) {
+      return this.toKeyedSeq().reverse().findKey(predicate, context);
+    },
+
+    first: function first(notSetValue) {
+      return this.find(returnTrue, null, notSetValue);
+    },
+
+    flatMap: function flatMap(mapper, context) {
+      return reify(this, flatMapFactory(this, mapper, context));
+    },
+
+    flatten: function flatten(depth) {
+      return reify(this, flattenFactory(this, depth, true));
+    },
+
+    fromEntrySeq: function fromEntrySeq() {
+      return new FromEntriesSequence(this);
+    },
+
+    get: function get(searchKey, notSetValue) {
+      return this.find(function (_, key) { return is(key, searchKey); }, undefined, notSetValue);
+    },
+
+    getIn: getIn,
+
+    groupBy: function groupBy(grouper, context) {
+      return groupByFactory(this, grouper, context);
+    },
+
+    has: function has(searchKey) {
+      return this.get(searchKey, NOT_SET) !== NOT_SET;
+    },
+
+    hasIn: hasIn,
+
+    isSubset: function isSubset(iter) {
+      iter = typeof iter.includes === 'function' ? iter : Collection(iter);
+      return this.every(function (value) { return iter.includes(value); });
+    },
+
+    isSuperset: function isSuperset(iter) {
+      iter = typeof iter.isSubset === 'function' ? iter : Collection(iter);
+      return iter.isSubset(this);
+    },
+
+    keyOf: function keyOf(searchValue) {
+      return this.findKey(function (value) { return is(value, searchValue); });
+    },
+
+    keySeq: function keySeq() {
+      return this.toSeq().map(keyMapper).toIndexedSeq();
+    },
+
+    last: function last(notSetValue) {
+      return this.toSeq().reverse().first(notSetValue);
+    },
+
+    lastKeyOf: function lastKeyOf(searchValue) {
+      return this.toKeyedSeq().reverse().keyOf(searchValue);
+    },
+
+    max: function max(comparator) {
+      return maxFactory(this, comparator);
+    },
+
+    maxBy: function maxBy(mapper, comparator) {
+      return maxFactory(this, comparator, mapper);
+    },
+
+    min: function min(comparator) {
+      return maxFactory(
+        this,
+        comparator ? neg(comparator) : defaultNegComparator
+      );
+    },
+
+    minBy: function minBy(mapper, comparator) {
+      return maxFactory(
+        this,
+        comparator ? neg(comparator) : defaultNegComparator,
+        mapper
+      );
+    },
+
+    rest: function rest() {
+      return this.slice(1);
+    },
+
+    skip: function skip(amount) {
+      return amount === 0 ? this : this.slice(Math.max(0, amount));
+    },
+
+    skipLast: function skipLast(amount) {
+      return amount === 0 ? this : this.slice(0, -Math.max(0, amount));
+    },
+
+    skipWhile: function skipWhile(predicate, context) {
+      return reify(this, skipWhileFactory(this, predicate, context, true));
+    },
+
+    skipUntil: function skipUntil(predicate, context) {
+      return this.skipWhile(not(predicate), context);
+    },
+
+    sortBy: function sortBy(mapper, comparator) {
+      return reify(this, sortFactory(this, comparator, mapper));
+    },
+
+    take: function take(amount) {
+      return this.slice(0, Math.max(0, amount));
+    },
+
+    takeLast: function takeLast(amount) {
+      return this.slice(-Math.max(0, amount));
+    },
+
+    takeWhile: function takeWhile(predicate, context) {
+      return reify(this, takeWhileFactory(this, predicate, context));
+    },
+
+    takeUntil: function takeUntil(predicate, context) {
+      return this.takeWhile(not(predicate), context);
+    },
+
+    update: function update(fn) {
+      return fn(this);
+    },
+
+    valueSeq: function valueSeq() {
+      return this.toIndexedSeq();
+    },
+
+    // ### Hashable Object
+
+    hashCode: function hashCode() {
+      return this.__hash || (this.__hash = hashCollection(this));
+    },
+
+    // ### Internal
+
+    // abstract __iterate(fn, reverse)
+
+    // abstract __iterator(type, reverse)
+  });
+
+  var CollectionPrototype = Collection.prototype;
+  CollectionPrototype[IS_COLLECTION_SYMBOL] = true;
+  CollectionPrototype[ITERATOR_SYMBOL] = CollectionPrototype.values;
+  CollectionPrototype.toJSON = CollectionPrototype.toArray;
+  CollectionPrototype.__toStringMapper = quoteString;
+  CollectionPrototype.inspect = CollectionPrototype.toSource = function () {
+    return this.toString();
+  };
+  CollectionPrototype.chain = CollectionPrototype.flatMap;
+  CollectionPrototype.contains = CollectionPrototype.includes;
+
+  mixin(KeyedCollection, {
+    // ### More sequential methods
+
+    flip: function flip() {
+      return reify(this, flipFactory(this));
+    },
+
+    mapEntries: function mapEntries(mapper, context) {
+      var this$1$1 = this;
+
+      var iterations = 0;
+      return reify(
+        this,
+        this.toSeq()
+          .map(function (v, k) { return mapper.call(context, [k, v], iterations++, this$1$1); })
+          .fromEntrySeq()
+      );
+    },
+
+    mapKeys: function mapKeys(mapper, context) {
+      var this$1$1 = this;
+
+      return reify(
+        this,
+        this.toSeq()
+          .flip()
+          .map(function (k, v) { return mapper.call(context, k, v, this$1$1); })
+          .flip()
+      );
+    },
+  });
+
+  var KeyedCollectionPrototype = KeyedCollection.prototype;
+  KeyedCollectionPrototype[IS_KEYED_SYMBOL] = true;
+  KeyedCollectionPrototype[ITERATOR_SYMBOL] = CollectionPrototype.entries;
+  KeyedCollectionPrototype.toJSON = toObject;
+  KeyedCollectionPrototype.__toStringMapper = function (v, k) { return quoteString(k) + ': ' + quoteString(v); };
+
+  mixin(IndexedCollection, {
+    // ### Conversion to other types
+
+    toKeyedSeq: function toKeyedSeq() {
+      return new ToKeyedSequence(this, false);
+    },
+
+    // ### ES6 Collection methods (ES6 Array and Map)
+
+    filter: function filter(predicate, context) {
+      return reify(this, filterFactory(this, predicate, context, false));
+    },
+
+    findIndex: function findIndex(predicate, context) {
+      var entry = this.findEntry(predicate, context);
+      return entry ? entry[0] : -1;
+    },
+
+    indexOf: function indexOf(searchValue) {
+      var key = this.keyOf(searchValue);
+      return key === undefined ? -1 : key;
+    },
+
+    lastIndexOf: function lastIndexOf(searchValue) {
+      var key = this.lastKeyOf(searchValue);
+      return key === undefined ? -1 : key;
+    },
+
+    reverse: function reverse() {
+      return reify(this, reverseFactory(this, false));
+    },
+
+    slice: function slice(begin, end) {
+      return reify(this, sliceFactory(this, begin, end, false));
+    },
+
+    splice: function splice(index, removeNum /*, ...values*/) {
+      var numArgs = arguments.length;
+      removeNum = Math.max(removeNum || 0, 0);
+      if (numArgs === 0 || (numArgs === 2 && !removeNum)) {
+        return this;
+      }
+      // If index is negative, it should resolve relative to the size of the
+      // collection. However size may be expensive to compute if not cached, so
+      // only call count() if the number is in fact negative.
+      index = resolveBegin(index, index < 0 ? this.count() : this.size);
+      var spliced = this.slice(0, index);
+      return reify(
+        this,
+        numArgs === 1
+          ? spliced
+          : spliced.concat(arrCopy(arguments, 2), this.slice(index + removeNum))
+      );
+    },
+
+    // ### More collection methods
+
+    findLastIndex: function findLastIndex(predicate, context) {
+      var entry = this.findLastEntry(predicate, context);
+      return entry ? entry[0] : -1;
+    },
+
+    first: function first(notSetValue) {
+      return this.get(0, notSetValue);
+    },
+
+    flatten: function flatten(depth) {
+      return reify(this, flattenFactory(this, depth, false));
+    },
+
+    get: function get(index, notSetValue) {
+      index = wrapIndex(this, index);
+      return index < 0 ||
+        this.size === Infinity ||
+        (this.size !== undefined && index > this.size)
+        ? notSetValue
+        : this.find(function (_, key) { return key === index; }, undefined, notSetValue);
+    },
+
+    has: function has(index) {
+      index = wrapIndex(this, index);
+      return (
+        index >= 0 &&
+        (this.size !== undefined
+          ? this.size === Infinity || index < this.size
+          : this.indexOf(index) !== -1)
+      );
+    },
+
+    interpose: function interpose(separator) {
+      return reify(this, interposeFactory(this, separator));
+    },
+
+    interleave: function interleave(/*...collections*/) {
+      var collections = [this].concat(arrCopy(arguments));
+      var zipped = zipWithFactory(this.toSeq(), IndexedSeq.of, collections);
+      var interleaved = zipped.flatten(true);
+      if (zipped.size) {
+        interleaved.size = zipped.size * collections.length;
+      }
+      return reify(this, interleaved);
+    },
+
+    keySeq: function keySeq() {
+      return Range(0, this.size);
+    },
+
+    last: function last(notSetValue) {
+      return this.get(-1, notSetValue);
+    },
+
+    skipWhile: function skipWhile(predicate, context) {
+      return reify(this, skipWhileFactory(this, predicate, context, false));
+    },
+
+    zip: function zip(/*, ...collections */) {
+      var collections = [this].concat(arrCopy(arguments));
+      return reify(this, zipWithFactory(this, defaultZipper, collections));
+    },
+
+    zipAll: function zipAll(/*, ...collections */) {
+      var collections = [this].concat(arrCopy(arguments));
+      return reify(this, zipWithFactory(this, defaultZipper, collections, true));
+    },
+
+    zipWith: function zipWith(zipper /*, ...collections */) {
+      var collections = arrCopy(arguments);
+      collections[0] = this;
+      return reify(this, zipWithFactory(this, zipper, collections));
+    },
+  });
+
+  var IndexedCollectionPrototype = IndexedCollection.prototype;
+  IndexedCollectionPrototype[IS_INDEXED_SYMBOL] = true;
+  IndexedCollectionPrototype[IS_ORDERED_SYMBOL] = true;
+
+  mixin(SetCollection, {
+    // ### ES6 Collection methods (ES6 Array and Map)
+
+    get: function get(value, notSetValue) {
+      return this.has(value) ? value : notSetValue;
+    },
+
+    includes: function includes(value) {
+      return this.has(value);
+    },
+
+    // ### More sequential methods
+
+    keySeq: function keySeq() {
+      return this.valueSeq();
+    },
+  });
+
+  var SetCollectionPrototype = SetCollection.prototype;
+  SetCollectionPrototype.has = CollectionPrototype.includes;
+  SetCollectionPrototype.contains = SetCollectionPrototype.includes;
+  SetCollectionPrototype.keys = SetCollectionPrototype.values;
+
+  // Mixin subclasses
+
+  mixin(KeyedSeq, KeyedCollectionPrototype);
+  mixin(IndexedSeq, IndexedCollectionPrototype);
+  mixin(SetSeq, SetCollectionPrototype);
+
+  // #pragma Helper functions
+
+  function reduce(collection, reducer, reduction, context, useFirst, reverse) {
+    assertNotInfinite(collection.size);
+    collection.__iterate(function (v, k, c) {
+      if (useFirst) {
+        useFirst = false;
+        reduction = v;
+      } else {
+        reduction = reducer.call(context, reduction, v, k, c);
+      }
+    }, reverse);
+    return reduction;
+  }
+
+  function keyMapper(v, k) {
+    return k;
+  }
+
+  function entryMapper(v, k) {
+    return [k, v];
+  }
+
+  function not(predicate) {
+    return function () {
+      return !predicate.apply(this, arguments);
+    };
+  }
+
+  function neg(predicate) {
+    return function () {
+      return -predicate.apply(this, arguments);
+    };
+  }
+
+  function defaultZipper() {
+    return arrCopy(arguments);
+  }
+
+  function defaultNegComparator(a, b) {
+    return a < b ? 1 : a > b ? -1 : 0;
+  }
+
+  function hashCollection(collection) {
+    if (collection.size === Infinity) {
+      return 0;
+    }
+    var ordered = isOrdered(collection);
+    var keyed = isKeyed(collection);
+    var h = ordered ? 1 : 0;
+
+    collection.__iterate(
+      keyed
+        ? ordered
+          ? function (v, k) {
+              h = (31 * h + hashMerge(hash(v), hash(k))) | 0;
+            }
+          : function (v, k) {
+              h = (h + hashMerge(hash(v), hash(k))) | 0;
+            }
+        : ordered
+        ? function (v) {
+            h = (31 * h + hash(v)) | 0;
+          }
+        : function (v) {
+            h = (h + hash(v)) | 0;
+          }
+    );
+
+    return murmurHashOfSize(collection.size, h);
+  }
+
+  function murmurHashOfSize(size, h) {
+    h = imul(h, 0xcc9e2d51);
+    h = imul((h << 15) | (h >>> -15), 0x1b873593);
+    h = imul((h << 13) | (h >>> -13), 5);
+    h = ((h + 0xe6546b64) | 0) ^ size;
+    h = imul(h ^ (h >>> 16), 0x85ebca6b);
+    h = imul(h ^ (h >>> 13), 0xc2b2ae35);
+    h = smi(h ^ (h >>> 16));
+    return h;
+  }
+
+  function hashMerge(a, b) {
+    return (a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2))) | 0; // int
+  }
+
+  var OrderedSet = /*@__PURE__*/(function (Set) {
+    function OrderedSet(value) {
+      // eslint-disable-next-line no-constructor-return
+      return value === undefined || value === null
+        ? emptyOrderedSet()
+        : isOrderedSet(value)
+        ? value
+        : emptyOrderedSet().withMutations(function (set) {
+            var iter = SetCollection(value);
+            assertNotInfinite(iter.size);
+            iter.forEach(function (v) { return set.add(v); });
+          });
+    }
+
+    if ( Set ) OrderedSet.__proto__ = Set;
+    OrderedSet.prototype = Object.create( Set && Set.prototype );
+    OrderedSet.prototype.constructor = OrderedSet;
+
+    OrderedSet.of = function of (/*...values*/) {
+      return this(arguments);
+    };
+
+    OrderedSet.fromKeys = function fromKeys (value) {
+      return this(KeyedCollection(value).keySeq());
+    };
+
+    OrderedSet.prototype.toString = function toString () {
+      return this.__toString('OrderedSet {', '}');
+    };
+
+    return OrderedSet;
+  }(Set));
+
+  OrderedSet.isOrderedSet = isOrderedSet;
+
+  var OrderedSetPrototype = OrderedSet.prototype;
+  OrderedSetPrototype[IS_ORDERED_SYMBOL] = true;
+  OrderedSetPrototype.zip = IndexedCollectionPrototype.zip;
+  OrderedSetPrototype.zipWith = IndexedCollectionPrototype.zipWith;
+  OrderedSetPrototype.zipAll = IndexedCollectionPrototype.zipAll;
+
+  OrderedSetPrototype.__empty = emptyOrderedSet;
+  OrderedSetPrototype.__make = makeOrderedSet;
+
+  function makeOrderedSet(map, ownerID) {
+    var set = Object.create(OrderedSetPrototype);
+    set.size = map ? map.size : 0;
+    set._map = map;
+    set.__ownerID = ownerID;
+    return set;
+  }
+
+  var EMPTY_ORDERED_SET;
+  function emptyOrderedSet() {
+    return (
+      EMPTY_ORDERED_SET || (EMPTY_ORDERED_SET = makeOrderedSet(emptyOrderedMap()))
+    );
+  }
+
+  var PairSorting = {
+    LeftThenRight: -1,
+    RightThenLeft: +1,
+  };
+
+  function throwOnInvalidDefaultValues(defaultValues) {
+    if (isRecord(defaultValues)) {
+      throw new Error(
+        'Can not call `Record` with an immutable Record as default values. Use a plain javascript object instead.'
+      );
+    }
+
+    if (isImmutable(defaultValues)) {
+      throw new Error(
+        'Can not call `Record` with an immutable Collection as default values. Use a plain javascript object instead.'
+      );
+    }
+
+    if (defaultValues === null || typeof defaultValues !== 'object') {
+      throw new Error(
+        'Can not call `Record` with a non-object as default values. Use a plain javascript object instead.'
+      );
+    }
+  }
+
+  var Record = function Record(defaultValues, name) {
+    var hasInitialized;
+
+    throwOnInvalidDefaultValues(defaultValues);
+
+    var RecordType = function Record(values) {
+      var this$1$1 = this;
+
+      if (values instanceof RecordType) {
+        return values;
+      }
+      if (!(this instanceof RecordType)) {
+        return new RecordType(values);
+      }
+      if (!hasInitialized) {
+        hasInitialized = true;
+        var keys = Object.keys(defaultValues);
+        var indices = (RecordTypePrototype._indices = {});
+        // Deprecated: left to attempt not to break any external code which
+        // relies on a ._name property existing on record instances.
+        // Use Record.getDescriptiveName() instead
+        RecordTypePrototype._name = name;
+        RecordTypePrototype._keys = keys;
+        RecordTypePrototype._defaultValues = defaultValues;
+        for (var i = 0; i < keys.length; i++) {
+          var propName = keys[i];
+          indices[propName] = i;
+          if (RecordTypePrototype[propName]) {
+            /* eslint-disable no-console */
+            typeof console === 'object' &&
+              console.warn &&
+              console.warn(
+                'Cannot define ' +
+                  recordName(this) +
+                  ' with property "' +
+                  propName +
+                  '" since that property name is part of the Record API.'
+              );
+            /* eslint-enable no-console */
+          } else {
+            setProp(RecordTypePrototype, propName);
+          }
+        }
+      }
+      this.__ownerID = undefined;
+      this._values = List().withMutations(function (l) {
+        l.setSize(this$1$1._keys.length);
+        KeyedCollection(values).forEach(function (v, k) {
+          l.set(this$1$1._indices[k], v === this$1$1._defaultValues[k] ? undefined : v);
+        });
+      });
+      return this;
+    };
+
+    var RecordTypePrototype = (RecordType.prototype =
+      Object.create(RecordPrototype));
+    RecordTypePrototype.constructor = RecordType;
+
+    if (name) {
+      RecordType.displayName = name;
+    }
+
+    // eslint-disable-next-line no-constructor-return
+    return RecordType;
+  };
+
+  Record.prototype.toString = function toString () {
+    var str = recordName(this) + ' { ';
+    var keys = this._keys;
+    var k;
+    for (var i = 0, l = keys.length; i !== l; i++) {
+      k = keys[i];
+      str += (i ? ', ' : '') + k + ': ' + quoteString(this.get(k));
+    }
+    return str + ' }';
+  };
+
+  Record.prototype.equals = function equals (other) {
+    return (
+      this === other ||
+      (isRecord(other) && recordSeq(this).equals(recordSeq(other)))
+    );
+  };
+
+  Record.prototype.hashCode = function hashCode () {
+    return recordSeq(this).hashCode();
+  };
+
+  // @pragma Access
+
+  Record.prototype.has = function has (k) {
+    return this._indices.hasOwnProperty(k);
+  };
+
+  Record.prototype.get = function get (k, notSetValue) {
+    if (!this.has(k)) {
+      return notSetValue;
+    }
+    var index = this._indices[k];
+    var value = this._values.get(index);
+    return value === undefined ? this._defaultValues[k] : value;
+  };
+
+  // @pragma Modification
+
+  Record.prototype.set = function set (k, v) {
+    if (this.has(k)) {
+      var newValues = this._values.set(
+        this._indices[k],
+        v === this._defaultValues[k] ? undefined : v
+      );
+      if (newValues !== this._values && !this.__ownerID) {
+        return makeRecord(this, newValues);
+      }
+    }
+    return this;
+  };
+
+  Record.prototype.remove = function remove (k) {
+    return this.set(k);
+  };
+
+  Record.prototype.clear = function clear () {
+    var newValues = this._values.clear().setSize(this._keys.length);
+
+    return this.__ownerID ? this : makeRecord(this, newValues);
+  };
+
+  Record.prototype.wasAltered = function wasAltered () {
+    return this._values.wasAltered();
+  };
+
+  Record.prototype.toSeq = function toSeq () {
+    return recordSeq(this);
+  };
+
+  Record.prototype.toJS = function toJS$1 () {
+    return toJS(this);
+  };
+
+  Record.prototype.entries = function entries () {
+    return this.__iterator(ITERATE_ENTRIES);
+  };
+
+  Record.prototype.__iterator = function __iterator (type, reverse) {
+    return recordSeq(this).__iterator(type, reverse);
+  };
+
+  Record.prototype.__iterate = function __iterate (fn, reverse) {
+    return recordSeq(this).__iterate(fn, reverse);
+  };
+
+  Record.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+    if (ownerID === this.__ownerID) {
+      return this;
+    }
+    var newValues = this._values.__ensureOwner(ownerID);
+    if (!ownerID) {
+      this.__ownerID = ownerID;
+      this._values = newValues;
+      return this;
+    }
+    return makeRecord(this, newValues, ownerID);
+  };
+
+  Record.isRecord = isRecord;
+  Record.getDescriptiveName = recordName;
+  var RecordPrototype = Record.prototype;
+  RecordPrototype[IS_RECORD_SYMBOL] = true;
+  RecordPrototype[DELETE] = RecordPrototype.remove;
+  RecordPrototype.deleteIn = RecordPrototype.removeIn = deleteIn;
+  RecordPrototype.getIn = getIn;
+  RecordPrototype.hasIn = CollectionPrototype.hasIn;
+  RecordPrototype.merge = merge$1;
+  RecordPrototype.mergeWith = mergeWith$1;
+  RecordPrototype.mergeIn = mergeIn;
+  RecordPrototype.mergeDeep = mergeDeep;
+  RecordPrototype.mergeDeepWith = mergeDeepWith;
+  RecordPrototype.mergeDeepIn = mergeDeepIn;
+  RecordPrototype.setIn = setIn;
+  RecordPrototype.update = update;
+  RecordPrototype.updateIn = updateIn;
+  RecordPrototype.withMutations = withMutations;
+  RecordPrototype.asMutable = asMutable;
+  RecordPrototype.asImmutable = asImmutable;
+  RecordPrototype[ITERATOR_SYMBOL] = RecordPrototype.entries;
+  RecordPrototype.toJSON = RecordPrototype.toObject =
+    CollectionPrototype.toObject;
+  RecordPrototype.inspect = RecordPrototype.toSource = function () {
+    return this.toString();
+  };
+
+  function makeRecord(likeRecord, values, ownerID) {
+    var record = Object.create(Object.getPrototypeOf(likeRecord));
+    record._values = values;
+    record.__ownerID = ownerID;
+    return record;
+  }
+
+  function recordName(record) {
+    return record.constructor.displayName || record.constructor.name || 'Record';
+  }
+
+  function recordSeq(record) {
+    return keyedSeqFromValue(record._keys.map(function (k) { return [k, record.get(k)]; }));
+  }
+
+  function setProp(prototype, name) {
+    try {
+      Object.defineProperty(prototype, name, {
+        get: function () {
+          return this.get(name);
+        },
+        set: function (value) {
+          invariant(this.__ownerID, 'Cannot set on an immutable record.');
+          this.set(name, value);
+        },
+      });
+    } catch (error) {
+      // Object.defineProperty failed. Probably IE8.
+    }
+  }
+
+  /**
+   * Returns a lazy Seq of `value` repeated `times` times. When `times` is
+   * undefined, returns an infinite sequence of `value`.
+   */
+  var Repeat = /*@__PURE__*/(function (IndexedSeq) {
+    function Repeat(value, times) {
+      if (!(this instanceof Repeat)) {
+        // eslint-disable-next-line no-constructor-return
+        return new Repeat(value, times);
+      }
+      this._value = value;
+      this.size = times === undefined ? Infinity : Math.max(0, times);
+      if (this.size === 0) {
+        if (EMPTY_REPEAT) {
+          // eslint-disable-next-line no-constructor-return
+          return EMPTY_REPEAT;
+        }
+        // eslint-disable-next-line @typescript-eslint/no-this-alias
+        EMPTY_REPEAT = this;
+      }
+    }
+
+    if ( IndexedSeq ) Repeat.__proto__ = IndexedSeq;
+    Repeat.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+    Repeat.prototype.constructor = Repeat;
+
+    Repeat.prototype.toString = function toString () {
+      if (this.size === 0) {
+        return 'Repeat []';
+      }
+      return 'Repeat [ ' + this._value + ' ' + this.size + ' times ]';
+    };
+
+    Repeat.prototype.get = function get (index, notSetValue) {
+      return this.has(index) ? this._value : notSetValue;
+    };
+
+    Repeat.prototype.includes = function includes (searchValue) {
+      return is(this._value, searchValue);
+    };
+
+    Repeat.prototype.slice = function slice (begin, end) {
+      var size = this.size;
+      return wholeSlice(begin, end, size)
+        ? this
+        : new Repeat(
+            this._value,
+            resolveEnd(end, size) - resolveBegin(begin, size)
+          );
+    };
+
+    Repeat.prototype.reverse = function reverse () {
+      return this;
+    };
+
+    Repeat.prototype.indexOf = function indexOf (searchValue) {
+      if (is(this._value, searchValue)) {
+        return 0;
+      }
+      return -1;
+    };
+
+    Repeat.prototype.lastIndexOf = function lastIndexOf (searchValue) {
+      if (is(this._value, searchValue)) {
+        return this.size;
+      }
+      return -1;
+    };
+
+    Repeat.prototype.__iterate = function __iterate (fn, reverse) {
+      var size = this.size;
+      var i = 0;
+      while (i !== size) {
+        if (fn(this._value, reverse ? size - ++i : i++, this) === false) {
+          break;
+        }
+      }
+      return i;
+    };
+
+    Repeat.prototype.__iterator = function __iterator (type, reverse) {
+      var this$1$1 = this;
+
+      var size = this.size;
+      var i = 0;
+      return new Iterator(function () { return i === size
+          ? iteratorDone()
+          : iteratorValue(type, reverse ? size - ++i : i++, this$1$1._value); }
+      );
+    };
+
+    Repeat.prototype.equals = function equals (other) {
+      return other instanceof Repeat
+        ? is(this._value, other._value)
+        : deepEqual(this, other);
+    };
+
+    return Repeat;
+  }(IndexedSeq));
+
+  var EMPTY_REPEAT;
+
+  function fromJS(value, converter) {
+    return fromJSWith(
+      [],
+      converter || defaultConverter,
+      value,
+      '',
+      converter && converter.length > 2 ? [] : undefined,
+      { '': value }
+    );
+  }
+
+  function fromJSWith(stack, converter, value, key, keyPath, parentValue) {
+    if (
+      typeof value !== 'string' &&
+      !isImmutable(value) &&
+      (isArrayLike(value) || hasIterator(value) || isPlainObject(value))
+    ) {
+      if (~stack.indexOf(value)) {
+        throw new TypeError('Cannot convert circular structure to Immutable');
+      }
+      stack.push(value);
+      keyPath && key !== '' && keyPath.push(key);
+      var converted = converter.call(
+        parentValue,
+        key,
+        Seq(value).map(function (v, k) { return fromJSWith(stack, converter, v, k, keyPath, value); }
+        ),
+        keyPath && keyPath.slice()
+      );
+      stack.pop();
+      keyPath && keyPath.pop();
+      return converted;
+    }
+    return value;
+  }
+
+  function defaultConverter(k, v) {
+    // Effectively the opposite of "Collection.toSeq()"
+    return isIndexed(v) ? v.toList() : isKeyed(v) ? v.toMap() : v.toSet();
+  }
+
+  var version = "5.0.3";
+
+  // Note: Iterable is deprecated
+  var Iterable = Collection;
+
+  exports.Collection = Collection;
+  exports.Iterable = Iterable;
+  exports.List = List;
+  exports.Map = Map;
+  exports.OrderedMap = OrderedMap;
+  exports.OrderedSet = OrderedSet;
+  exports.PairSorting = PairSorting;
+  exports.Range = Range;
+  exports.Record = Record;
+  exports.Repeat = Repeat;
+  exports.Seq = Seq;
+  exports.Set = Set;
+  exports.Stack = Stack;
+  exports.fromJS = fromJS;
+  exports.get = get;
+  exports.getIn = getIn$1;
+  exports.has = has;
+  exports.hasIn = hasIn$1;
+  exports.hash = hash;
+  exports.is = is;
+  exports.isAssociative = isAssociative;
+  exports.isCollection = isCollection;
+  exports.isImmutable = isImmutable;
+  exports.isIndexed = isIndexed;
+  exports.isKeyed = isKeyed;
+  exports.isList = isList;
+  exports.isMap = isMap;
+  exports.isOrdered = isOrdered;
+  exports.isOrderedMap = isOrderedMap;
+  exports.isOrderedSet = isOrderedSet;
+  exports.isPlainObject = isPlainObject;
+  exports.isRecord = isRecord;
+  exports.isSeq = isSeq;
+  exports.isSet = isSet;
+  exports.isStack = isStack;
+  exports.isValueObject = isValueObject;
+  exports.merge = merge;
+  exports.mergeDeep = mergeDeep$1;
+  exports.mergeDeepWith = mergeDeepWith$1;
+  exports.mergeWith = mergeWith;
+  exports.remove = remove;
+  exports.removeIn = removeIn;
+  exports.set = set;
+  exports.setIn = setIn$1;
+  exports.update = update$1;
+  exports.updateIn = updateIn$1;
+  exports.version = version;
+
+}));
Index: imaps-frontend/node_modules/immutable/dist/immutable.js.flow
===================================================================
--- imaps-frontend/node_modules/immutable/dist/immutable.js.flow	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
+++ imaps-frontend/node_modules/immutable/dist/immutable.js.flow	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
@@ -0,0 +1,2414 @@
+/**
+ * This file provides type definitions for use with the Flow type checker.
+ *
+ * An important caveat when using these definitions is that the types for
+ * `Collection.Keyed`, `Collection.Indexed`, `Seq.Keyed`, and so on are stubs.
+ * When referring to those types, you can get the proper definitions by
+ * importing the types `KeyedCollection`, `IndexedCollection`, `KeyedSeq`, etc.
+ * For example,
+ *
+ *     import { Seq } from 'immutable'
+ *     import type { IndexedCollection, IndexedSeq } from 'immutable'
+ *
+ *     const someSeq: IndexedSeq<number> = Seq.Indexed.of(1, 2, 3)
+ *
+ *     function takesASeq<T, TS: IndexedCollection<T>>(iter: TS): TS {
+ *       return iter.butLast()
+ *     }
+ *
+ *     takesASeq(someSeq)
+ *
+ * @flow strict
+ */
+
+// Helper type that represents plain objects allowed as arguments to
+// some constructors and functions.
+type PlainObjInput<K, V> = { +[key: K]: V, __proto__: null };
+
+type K<T> = $Keys<T>;
+
+// Helper types to extract the "keys" and "values" use by the *In() methods.
+type $KeyOf<C> = $Call<
+  (<K>(?_Collection<K, mixed>) => K) &
+    (<T>(?$ReadOnlyArray<T>) => number) &
+    (<T>(?RecordInstance<T> | T) => $Keys<T>) &
+    (<T: Object>(T) => $Keys<T>),
+  C
+>;
+
+type $ValOf<C, K = $KeyOf<C>> = $Call<
+  (<V>(?_Collection<any, V>) => V) &
+    (<T>(?$ReadOnlyArray<T>) => T) &
+    (<T, K: $Keys<T>>(?RecordInstance<T> | T, K) => $ElementType<T, K>) &
+    (<T: Object>(T) => $Values<T>),
+  C,
+  K
+>;
+
+type $IterableOf<C> = $Call<
+  (<V: Array<any> | IndexedCollection<any> | SetCollection<any>>(
+    V
+  ) => Iterable<$ValOf<V>>) &
+    (<
+      V:
+        | KeyedCollection<any, any>
+        | RecordInstance<any>
+        | PlainObjInput<any, any>
+    >(
+      V
+    ) => Iterable<[$KeyOf<V>, $ValOf<V>]>),
+  C
+>;
+
+const PairSorting: $ReadOnly<{ LeftThenRight: number, RightThenLeft: number }> =
+  {
+    LeftThenRight: -1,
+    RightThenLeft: +1,
+  };
+
+type Comparator<T> = (left: T, right: T) => number;
+
+declare class _Collection<K, +V> implements ValueObject {
+  equals(other: mixed): boolean;
+  hashCode(): number;
+  get(key: K, ..._: []): V | void;
+  get<NSV>(key: K, notSetValue: NSV): V | NSV;
+  has(key: K): boolean;
+  includes(value: V): boolean;
+  contains(value: V): boolean;
+  first(): V | void;
+  first<NSV>(notSetValue: NSV): V | NSV;
+  last(): V | void;
+  last<NSV>(notSetValue: NSV): V | NSV;
+
+  hasIn(keyPath: Iterable<mixed>): boolean;
+
+  getIn(keyPath: [], notSetValue?: mixed): this;
+  getIn<NSV>(keyPath: [K], notSetValue: NSV): V | NSV;
+  getIn<NSV, K2: $KeyOf<V>>(
+    keyPath: [K, K2],
+    notSetValue: NSV
+  ): $ValOf<V, K2> | NSV;
+  getIn<NSV, K2: $KeyOf<V>, K3: $KeyOf<$ValOf<V, K2>>>(
+    keyPath: [K, K2, K3],
+    notSetValue: NSV
+  ): $ValOf<$ValOf<V, K2>, K3> | NSV;
+  getIn<
+    NSV,
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>
+  >(
+    keyPath: [K, K2, K3, K4],
+    notSetValue: NSV
+  ): $ValOf<$ValOf<$ValOf<V, K2>, K3>, K4> | NSV;
+  getIn<
+    NSV,
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>>
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    notSetValue: NSV
+  ): $ValOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>, K5> | NSV;
+
+  update<U>(updater: (value: this) => U): U;
+
+  toJS(): Array<any> | { [key: string]: mixed };
+  toJSON(): Array<V> | { [key: string]: V };
+  toArray(): Array<V> | Array<[K, V]>;
+  toObject(): { [key: string]: V };
+  toMap(): Map<K, V>;
+  toOrderedMap(): OrderedMap<K, V>;
+  toSet(): Set<V>;
+  toOrderedSet(): OrderedSet<V>;
+  toList(): List<V>;
+  toStack(): Stack<V>;
+  toSeq(): Seq<K, V>;
+  toKeyedSeq(): KeyedSeq<K, V>;
+  toIndexedSeq(): IndexedSeq<V>;
+  toSetSeq(): SetSeq<V>;
+
+  keys(): Iterator<K>;
+  values(): Iterator<V>;
+  entries(): Iterator<[K, V]>;
+
+  keySeq(): IndexedSeq<K>;
+  valueSeq(): IndexedSeq<V>;
+  entrySeq(): IndexedSeq<[K, V]>;
+
+  reverse(): this;
+  sort(comparator?: Comparator<V>): this;
+
+  sortBy<C>(
+    comparatorValueMapper: (value: V, key: K, iter: this) => C,
+    comparator?: Comparator<C>
+  ): this;
+
+  groupBy<G>(
+    grouper: (value: V, key: K, iter: this) => G,
+    context?: mixed
+  ): KeyedSeq<G, this>;
+
+  forEach(
+    sideEffect: (value: V, key: K, iter: this) => any,
+    context?: mixed
+  ): number;
+
+  slice(begin?: number, end?: number): this;
+  rest(): this;
+  butLast(): this;
+  skip(amount: number): this;
+  skipLast(amount: number): this;
+  skipWhile(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): this;
+  skipUntil(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): this;
+  take(amount: number): this;
+  takeLast(amount: number): this;
+  takeWhile(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): this;
+  takeUntil(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): this;
+
+  filterNot(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): this;
+
+  reduce<R>(
+    reducer: (reduction: R, value: V, key: K, iter: this) => R,
+    initialReduction: R,
+    context?: mixed
+  ): R;
+  reduce<R>(reducer: (reduction: V | R, value: V, key: K, iter: this) => R): R;
+
+  reduceRight<R>(
+    reducer: (reduction: R, value: V, key: K, iter: this) => R,
+    initialReduction: R,
+    context?: mixed
+  ): R;
+  reduceRight<R>(
+    reducer: (reduction: V | R, value: V, key: K, iter: this) => R
+  ): R;
+
+  every(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): boolean;
+  some(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): boolean;
+  join(separator?: string): string;
+  isEmpty(): boolean;
+  count(
+    predicate?: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): number;
+  countBy<G>(
+    grouper: (value: V, key: K, iter: this) => G,
+    context?: mixed
+  ): Map<G, number>;
+
+  find(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed,
+    notSetValue?: V
+  ): V | void;
+  findLast(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed,
+    notSetValue?: V
+  ): V | void;
+
+  findEntry(predicate: (value: V, key: K, iter: this) => mixed): [K, V] | void;
+  findLastEntry(
+    predicate: (value: V, key: K, iter: this) => mixed
+  ): [K, V] | void;
+
+  findKey(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): K | void;
+  findLastKey(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): K | void;
+
+  keyOf(searchValue: V): K | void;
+  lastKeyOf(searchValue: V): K | void;
+
+  max(comparator?: Comparator<V>): V;
+  maxBy<C>(
+    comparatorValueMapper: (value: V, key: K, iter: this) => C,
+    comparator?: Comparator<C>
+  ): V;
+  min(comparator?: Comparator<V>): V;
+  minBy<C>(
+    comparatorValueMapper: (value: V, key: K, iter: this) => C,
+    comparator?: Comparator<C>
+  ): V;
+
+  isSubset(iter: Iterable<V>): boolean;
+  isSuperset(iter: Iterable<V>): boolean;
+}
+
+declare function isImmutable(
+  maybeImmutable: mixed
+): boolean %checks(maybeImmutable instanceof Collection);
+declare function isCollection(
+  maybeCollection: mixed
+): boolean %checks(maybeCollection instanceof Collection);
+declare function isKeyed(
+  maybeKeyed: mixed
+): boolean %checks(maybeKeyed instanceof KeyedCollection);
+declare function isIndexed(
+  maybeIndexed: mixed
+): boolean %checks(maybeIndexed instanceof IndexedCollection);
+declare function isAssociative(
+  maybeAssociative: mixed
+): boolean %checks(maybeAssociative instanceof KeyedCollection ||
+  maybeAssociative instanceof IndexedCollection);
+declare function isOrdered(
+  maybeOrdered: mixed
+): boolean %checks(maybeOrdered instanceof IndexedCollection ||
+  maybeOrdered instanceof OrderedMap ||
+  maybeOrdered instanceof OrderedSet);
+declare function isValueObject(maybeValue: mixed): boolean;
+
+declare function isSeq(maybeSeq: any): boolean %checks(maybeSeq instanceof Seq);
+declare function isList(maybeList: any): boolean %checks(maybeList instanceof
+  List);
+declare function isMap(maybeMap: any): boolean %checks(maybeMap instanceof Map);
+declare function isOrderedMap(
+  maybeOrderedMap: any
+): boolean %checks(maybeOrderedMap instanceof OrderedMap);
+declare function isStack(maybeStack: any): boolean %checks(maybeStack instanceof
+  Stack);
+declare function isSet(maybeSet: any): boolean %checks(maybeSet instanceof Set);
+declare function isOrderedSet(
+  maybeOrderedSet: any
+): boolean %checks(maybeOrderedSet instanceof OrderedSet);
+declare function isRecord(
+  maybeRecord: any
+): boolean %checks(maybeRecord instanceof Record);
+
+declare interface ValueObject {
+  equals(other: mixed): boolean;
+  hashCode(): number;
+}
+
+declare class Collection<K, +V> extends _Collection<K, V> {
+  static Keyed: typeof KeyedCollection;
+  static Indexed: typeof IndexedCollection;
+  static Set: typeof SetCollection;
+
+  static isCollection: typeof isCollection;
+  static isKeyed: typeof isKeyed;
+  static isIndexed: typeof isIndexed;
+  static isAssociative: typeof isAssociative;
+  static isOrdered: typeof isOrdered;
+}
+
+declare class KeyedCollection<K, +V> extends Collection<K, V> {
+  static <K, V>(
+    values?: Iterable<[K, V]> | PlainObjInput<K, V>
+  ): KeyedCollection<K, V>;
+
+  toJS(): { [key: string]: mixed };
+  toJSON(): { [key: string]: V };
+  toArray(): Array<[K, V]>;
+  @@iterator(): Iterator<[K, V]>;
+  toSeq(): KeyedSeq<K, V>;
+  flip(): KeyedCollection<V, K>;
+
+  concat<KC, VC>(
+    ...iters: Array<Iterable<[KC, VC]> | PlainObjInput<KC, VC>>
+  ): KeyedCollection<K | KC, V | VC>;
+
+  filter(predicate: typeof Boolean): KeyedCollection<K, $NonMaybeType<V>>;
+  filter(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): KeyedCollection<K, V>;
+
+  partition(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: V, key: K, iter: this) => M,
+    context?: mixed
+  ): KeyedCollection<K, M>;
+
+  mapKeys<M>(
+    mapper: (key: K, value: V, iter: this) => M,
+    context?: mixed
+  ): KeyedCollection<M, V>;
+
+  mapEntries<KM, VM>(
+    mapper: (entry: [K, V], index: number, iter: this) => [KM, VM],
+    context?: mixed
+  ): KeyedCollection<KM, VM>;
+
+  flatMap<KM, VM>(
+    mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+    context?: mixed
+  ): KeyedCollection<KM, VM>;
+
+  flatten(depth?: number): KeyedCollection<any, any>;
+  flatten(shallow?: boolean): KeyedCollection<any, any>;
+}
+
+Collection.Keyed = KeyedCollection;
+
+declare class IndexedCollection<+T> extends Collection<number, T> {
+  static <T>(iter?: Iterable<T>): IndexedCollection<T>;
+
+  toJS(): Array<mixed>;
+  toJSON(): Array<T>;
+  toArray(): Array<T>;
+  @@iterator(): Iterator<T>;
+  toSeq(): IndexedSeq<T>;
+  fromEntrySeq<K, V>(): KeyedSeq<K, V>;
+  interpose(separator: T): this;
+  interleave(...collections: Iterable<T>[]): this;
+  splice(index: number, removeNum: number, ...values: T[]): this;
+
+  zip<A>(a: Iterable<A>, ..._: []): IndexedCollection<[T, A]>;
+  zip<A, B>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): IndexedCollection<[T, A, B]>;
+  zip<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): IndexedCollection<[T, A, B, C]>;
+  zip<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): IndexedCollection<[T, A, B, C, D]>;
+  zip<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): IndexedCollection<[T, A, B, C, D, E]>;
+
+  zipAll<A>(a: Iterable<A>, ..._: []): IndexedCollection<[T | void, A | void]>;
+  zipAll<A, B>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): IndexedCollection<[T | void, A | void, B | void]>;
+  zipAll<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): IndexedCollection<[T | void, A | void, B | void, C | void]>;
+  zipAll<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): IndexedCollection<[T | void, A | void, B | void, C | void, D | void]>;
+  zipAll<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): IndexedCollection<
+    [T | void, A | void, B | void, C | void, D | void, E | void]
+  >;
+
+  zipWith<A, R>(
+    zipper: (value: T, a: A) => R,
+    a: Iterable<A>,
+    ..._: []
+  ): IndexedCollection<R>;
+  zipWith<A, B, R>(
+    zipper: (value: T, a: A, b: B) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): IndexedCollection<R>;
+  zipWith<A, B, C, R>(
+    zipper: (value: T, a: A, b: B, c: C) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): IndexedCollection<R>;
+  zipWith<A, B, C, D, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): IndexedCollection<R>;
+  zipWith<A, B, C, D, E, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D, e: E) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): IndexedCollection<R>;
+
+  indexOf(searchValue: T): number;
+  lastIndexOf(searchValue: T): number;
+  findIndex(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): number;
+  findLastIndex(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): number;
+
+  concat<C>(...iters: Array<Iterable<C> | C>): IndexedCollection<T | C>;
+
+  filter(predicate: typeof Boolean): IndexedCollection<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): IndexedCollection<T>;
+
+  partition(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: T, index: number, iter: this) => M,
+    context?: mixed
+  ): IndexedCollection<M>;
+
+  flatMap<M>(
+    mapper: (value: T, index: number, iter: this) => Iterable<M>,
+    context?: mixed
+  ): IndexedCollection<M>;
+
+  flatten(depth?: number): IndexedCollection<any>;
+  flatten(shallow?: boolean): IndexedCollection<any>;
+}
+
+declare class SetCollection<+T> extends Collection<T, T> {
+  static <T>(iter?: Iterable<T>): SetCollection<T>;
+
+  toJS(): Array<mixed>;
+  toJSON(): Array<T>;
+  toArray(): Array<T>;
+  @@iterator(): Iterator<T>;
+  toSeq(): SetSeq<T>;
+
+  concat<U>(...collections: Iterable<U>[]): SetCollection<T | U>;
+
+  // `filter`, `map` and `flatMap` cannot be defined further up the hierarchy,
+  // because the implementation for `KeyedCollection` allows the value type to
+  // change without constraining the key type. That does not work for
+  // `SetCollection` - the value and key types *must* match.
+  filter(predicate: typeof Boolean): SetCollection<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): SetCollection<T>;
+
+  partition(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: T, value: T, iter: this) => M,
+    context?: mixed
+  ): SetCollection<M>;
+
+  flatMap<M>(
+    mapper: (value: T, value: T, iter: this) => Iterable<M>,
+    context?: mixed
+  ): SetCollection<M>;
+
+  flatten(depth?: number): SetCollection<any>;
+  flatten(shallow?: boolean): SetCollection<any>;
+}
+
+declare function isSeq(maybeSeq: mixed): boolean %checks(maybeSeq instanceof
+  Seq);
+declare class Seq<K, +V> extends _Collection<K, V> {
+  static Keyed: typeof KeyedSeq;
+  static Indexed: typeof IndexedSeq;
+  static Set: typeof SetSeq;
+
+  static <K, V>(values: KeyedSeq<K, V>): KeyedSeq<K, V>;
+  static <T>(values: SetSeq<T>): SetSeq<K, V>;
+  static <T>(values: Iterable<T>): IndexedSeq<T>;
+  static <K, V>(values?: PlainObjInput<K, V>): KeyedSeq<K, V>;
+
+  static isSeq: typeof isSeq;
+
+  size: number | void;
+  cacheResult(): this;
+  toSeq(): this;
+}
+
+declare class KeyedSeq<K, +V> extends Seq<K, V> mixins KeyedCollection<K, V> {
+  static <K, V>(
+    values?: Iterable<[K, V]> | PlainObjInput<K, V>
+  ): KeyedSeq<K, V>;
+
+  // Override specialized return types
+  flip(): KeyedSeq<V, K>;
+
+  concat<KC, VC>(
+    ...iters: Array<Iterable<[KC, VC]> | PlainObjInput<KC, VC>>
+  ): KeyedSeq<K | KC, V | VC>;
+
+  filter(predicate: typeof Boolean): KeyedSeq<K, $NonMaybeType<V>>;
+  filter(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): KeyedSeq<K, V>;
+
+  partition(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: V, key: K, iter: this) => M,
+    context?: mixed
+  ): KeyedSeq<K, M>;
+
+  mapKeys<M>(
+    mapper: (key: K, value: V, iter: this) => M,
+    context?: mixed
+  ): KeyedSeq<M, V>;
+
+  mapEntries<KM, VM>(
+    mapper: (entry: [K, V], index: number, iter: this) => [KM, VM],
+    context?: mixed
+  ): KeyedSeq<KM, VM>;
+
+  flatMap<KM, VM>(
+    mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+    context?: mixed
+  ): KeyedSeq<KM, VM>;
+
+  flatten(depth?: number): KeyedSeq<any, any>;
+  flatten(shallow?: boolean): KeyedSeq<any, any>;
+}
+
+declare class IndexedSeq<+T>
+  extends Seq<number, T>
+  mixins IndexedCollection<T>
+{
+  static <T>(values?: Iterable<T>): IndexedSeq<T>;
+
+  static of<T>(...values: T[]): IndexedSeq<T>;
+
+  // Override specialized return types
+
+  concat<C>(...iters: Array<Iterable<C> | C>): IndexedSeq<T | C>;
+
+  filter(predicate: typeof Boolean): IndexedSeq<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): IndexedSeq<T>;
+
+  partition(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: T, index: number, iter: this) => M,
+    context?: mixed
+  ): IndexedSeq<M>;
+
+  flatMap<M>(
+    mapper: (value: T, index: number, iter: this) => Iterable<M>,
+    context?: mixed
+  ): IndexedSeq<M>;
+
+  flatten(depth?: number): IndexedSeq<any>;
+  flatten(shallow?: boolean): IndexedSeq<any>;
+
+  zip<A>(a: Iterable<A>, ..._: []): IndexedSeq<[T, A]>;
+  zip<A, B>(a: Iterable<A>, b: Iterable<B>, ..._: []): IndexedSeq<[T, A, B]>;
+  zip<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): IndexedSeq<[T, A, B, C]>;
+  zip<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): IndexedSeq<[T, A, B, C, D]>;
+  zip<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): IndexedSeq<[T, A, B, C, D, E]>;
+
+  zipAll<A>(a: Iterable<A>, ..._: []): IndexedSeq<[T | void, A | void]>;
+  zipAll<A, B>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): IndexedSeq<[T | void, A | void, B | void]>;
+  zipAll<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): IndexedSeq<[T | void, A | void, B | void, C | void]>;
+  zipAll<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): IndexedSeq<[T | void, A | void, B | void, C | void, D | void]>;
+  zipAll<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): IndexedSeq<[T | void, A | void, B | void, C | void, D | void, E | void]>;
+
+  zipWith<A, R>(
+    zipper: (value: T, a: A) => R,
+    a: Iterable<A>,
+    ..._: []
+  ): IndexedSeq<R>;
+  zipWith<A, B, R>(
+    zipper: (value: T, a: A, b: B) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): IndexedSeq<R>;
+  zipWith<A, B, C, R>(
+    zipper: (value: T, a: A, b: B, c: C) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): IndexedSeq<R>;
+  zipWith<A, B, C, D, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): IndexedSeq<R>;
+  zipWith<A, B, C, D, E, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D, e: E) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): IndexedSeq<R>;
+}
+
+declare class SetSeq<+T> extends Seq<T, T> mixins SetCollection<T> {
+  static <T>(values?: Iterable<T>): SetSeq<T>;
+
+  static of<T>(...values: T[]): SetSeq<T>;
+
+  // Override specialized return types
+
+  concat<U>(...collections: Iterable<U>[]): SetSeq<T | U>;
+
+  filter(predicate: typeof Boolean): SetSeq<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): SetSeq<T>;
+
+  partition(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: T, value: T, iter: this) => M,
+    context?: mixed
+  ): SetSeq<M>;
+
+  flatMap<M>(
+    mapper: (value: T, value: T, iter: this) => Iterable<M>,
+    context?: mixed
+  ): SetSeq<M>;
+
+  flatten(depth?: number): SetSeq<any>;
+  flatten(shallow?: boolean): SetSeq<any>;
+}
+
+declare class UpdatableInCollection<K, +V> {
+  setIn<S>(keyPath: [], value: S): S;
+  setIn(keyPath: [K], value: V): this;
+  setIn<K2: $KeyOf<V>, S: $ValOf<V, K2>>(keyPath: [K, K2], value: S): this;
+  setIn<K2: $KeyOf<V>, K3: $KeyOf<$ValOf<V, K2>>, S: $ValOf<$ValOf<V, K2>, K3>>(
+    keyPath: [K, K2, K3],
+    value: S
+  ): this;
+  setIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    S: $ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>
+  >(
+    keyPath: [K, K2, K3, K4],
+    value: S
+  ): this;
+  setIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>, K5>
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    value: S
+  ): this;
+
+  deleteIn(keyPath: []): void;
+  deleteIn(keyPath: [K]): this;
+  deleteIn<K2: $KeyOf<V>>(keyPath: [K, K2]): this;
+  deleteIn<K2: $KeyOf<V>, K3: $KeyOf<$ValOf<V, K2>>>(
+    keyPath: [K, K2, K3]
+  ): this;
+  deleteIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>
+  >(
+    keyPath: [K, K2, K3, K4]
+  ): this;
+  deleteIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>>
+  >(
+    keyPath: [K, K2, K3, K4, K5]
+  ): this;
+
+  removeIn(keyPath: []): void;
+  removeIn(keyPath: [K]): this;
+  removeIn<K2: $KeyOf<V>>(keyPath: [K, K2]): this;
+  removeIn<K2: $KeyOf<V>, K3: $KeyOf<$ValOf<V, K2>>>(
+    keyPath: [K, K2, K3]
+  ): this;
+  removeIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>
+  >(
+    keyPath: [K, K2, K3, K4]
+  ): this;
+  removeIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>>
+  >(
+    keyPath: [K, K2, K3, K4, K5]
+  ): this;
+
+  updateIn<U>(keyPath: [], notSetValue: mixed, updater: (value: this) => U): U;
+  updateIn<U>(keyPath: [], updater: (value: this) => U): U;
+  updateIn<NSV>(keyPath: [K], notSetValue: NSV, updater: (value: V) => V): this;
+  updateIn(keyPath: [K], updater: (value: V) => V): this;
+  updateIn<NSV, K2: $KeyOf<V>, S: $ValOf<V, K2>>(
+    keyPath: [K, K2],
+    notSetValue: NSV,
+    updater: (value: $ValOf<V, K2> | NSV) => S
+  ): this;
+  updateIn<K2: $KeyOf<V>, S: $ValOf<V, K2>>(
+    keyPath: [K, K2],
+    updater: (value: $ValOf<V, K2>) => S
+  ): this;
+  updateIn<
+    NSV,
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    S: $ValOf<$ValOf<V, K2>, K3>
+  >(
+    keyPath: [K, K2, K3],
+    notSetValue: NSV,
+    updater: (value: $ValOf<$ValOf<V, K2>, K3> | NSV) => S
+  ): this;
+  updateIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    S: $ValOf<$ValOf<V, K2>, K3>
+  >(
+    keyPath: [K, K2, K3],
+    updater: (value: $ValOf<$ValOf<V, K2>, K3>) => S
+  ): this;
+  updateIn<
+    NSV,
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    S: $ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>
+  >(
+    keyPath: [K, K2, K3, K4],
+    notSetValue: NSV,
+    updater: (value: $ValOf<$ValOf<$ValOf<V, K2>, K3>, K4> | NSV) => S
+  ): this;
+  updateIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    S: $ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>
+  >(
+    keyPath: [K, K2, K3, K4],
+    updater: (value: $ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>) => S
+  ): this;
+  updateIn<
+    NSV,
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>, K5>
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    notSetValue: NSV,
+    updater: (
+      value: $ValOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>, K5> | NSV
+    ) => S
+  ): this;
+  updateIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>, K5>
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    updater: (value: $ValOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>, K5>) => S
+  ): this;
+}
+
+declare function isList(maybeList: mixed): boolean %checks(maybeList instanceof
+  List);
+declare class List<+T>
+  extends IndexedCollection<T>
+  mixins UpdatableInCollection<number, T>
+{
+  static <T>(collection?: Iterable<T>): List<T>;
+
+  static of<T>(...values: T[]): List<T>;
+
+  static isList: typeof isList;
+
+  size: number;
+
+  set<U>(index: number, value: U): List<T | U>;
+  delete(index: number): this;
+  remove(index: number): this;
+  insert<U>(index: number, value: U): List<T | U>;
+  clear(): this;
+  push<U>(...values: U[]): List<T | U>;
+  pop(): this;
+  unshift<U>(...values: U[]): List<T | U>;
+  shift(): this;
+
+  update<U>(updater: (value: this) => U): U;
+  update<U>(index: number, updater: (value: T) => U): List<T | U>;
+  update<U>(
+    index: number,
+    notSetValue: U,
+    updater: (value: T) => U
+  ): List<T | U>;
+
+  merge<U>(...collections: Iterable<U>[]): List<T | U>;
+
+  setSize(size: number): this;
+
+  mergeIn(keyPath: Iterable<mixed>, ...collections: Iterable<mixed>[]): this;
+  mergeDeepIn(
+    keyPath: Iterable<mixed>,
+    ...collections: Iterable<mixed>[]
+  ): this;
+
+  withMutations(mutator: (mutable: this) => mixed): this;
+  asMutable(): this;
+  wasAltered(): boolean;
+  asImmutable(): this;
+
+  // Override specialized return types
+
+  concat<C>(...iters: Array<Iterable<C> | C>): List<T | C>;
+
+  filter(predicate: typeof Boolean): List<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): List<T>;
+
+  partition(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: T, index: number, iter: this) => M,
+    context?: mixed
+  ): List<M>;
+
+  flatMap<M>(
+    mapper: (value: T, index: number, iter: this) => Iterable<M>,
+    context?: mixed
+  ): List<M>;
+
+  flatten(depth?: number): List<any>;
+  flatten(shallow?: boolean): List<any>;
+
+  zip<A>(a: Iterable<A>, ..._: []): List<[T, A]>;
+  zip<A, B>(a: Iterable<A>, b: Iterable<B>, ..._: []): List<[T, A, B]>;
+  zip<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): List<[T, A, B, C]>;
+  zip<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): List<[T, A, B, C, D]>;
+  zip<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): List<[T, A, B, C, D, E]>;
+
+  zipAll<A>(a: Iterable<A>, ..._: []): List<[T | void, A | void]>;
+  zipAll<A, B>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): List<[T | void, A | void, B | void]>;
+  zipAll<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): List<[T | void, A | void, B | void, C | void]>;
+  zipAll<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): List<[T | void, A | void, B | void, C | void, D | void]>;
+  zipAll<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): List<[T | void, A | void, B | void, C | void, D | void, E | void]>;
+
+  zipWith<A, R>(
+    zipper: (value: T, a: A) => R,
+    a: Iterable<A>,
+    ..._: []
+  ): List<R>;
+  zipWith<A, B, R>(
+    zipper: (value: T, a: A, b: B) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): List<R>;
+  zipWith<A, B, C, R>(
+    zipper: (value: T, a: A, b: B, c: C) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): List<R>;
+  zipWith<A, B, C, D, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): List<R>;
+  zipWith<A, B, C, D, E, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D, e: E) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): List<R>;
+}
+
+declare function isMap(maybeMap: mixed): boolean %checks(maybeMap instanceof
+  Map);
+declare class Map<K, +V>
+  extends KeyedCollection<K, V>
+  mixins UpdatableInCollection<K, V>
+{
+  static <K, V>(values?: Iterable<[K, V]> | PlainObjInput<K, V>): Map<K, V>;
+
+  static isMap: typeof isMap;
+
+  size: number;
+
+  set<K_, V_>(key: K_, value: V_): Map<K | K_, V | V_>;
+  delete(key: K): this;
+  remove(key: K): this;
+  clear(): this;
+
+  deleteAll(keys: Iterable<K>): Map<K, V>;
+  removeAll(keys: Iterable<K>): Map<K, V>;
+
+  update<U>(updater: (value: this) => U): U;
+  update<V_>(key: K, updater: (value: V) => V_): Map<K, V | V_>;
+  update<V_>(
+    key: K,
+    notSetValue: V_,
+    updater: (value: V) => V_
+  ): Map<K, V | V_>;
+
+  merge<K_, V_>(
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): Map<K | K_, V | V_>;
+  concat<K_, V_>(
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): Map<K | K_, V | V_>;
+
+  mergeWith<K_, W, X>(
+    merger: (oldVal: V, newVal: W, key: K) => X,
+    ...collections: (Iterable<[K_, W]> | PlainObjInput<K_, W>)[]
+  ): Map<K | K_, V | W | X>;
+
+  mergeDeep<K_, V_>(
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): Map<K | K_, V | V_>;
+
+  mergeDeepWith<K_, V_>(
+    merger: (oldVal: any, newVal: any, key: any) => mixed,
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): Map<K | K_, V | V_>;
+
+  mergeIn(
+    keyPath: Iterable<mixed>,
+    ...collections: (Iterable<mixed> | PlainObjInput<mixed, mixed>)[]
+  ): this;
+  mergeDeepIn(
+    keyPath: Iterable<mixed>,
+    ...collections: (Iterable<mixed> | PlainObjInput<mixed, mixed>)[]
+  ): this;
+
+  withMutations(mutator: (mutable: this) => mixed): this;
+  asMutable(): this;
+  wasAltered(): boolean;
+  asImmutable(): this;
+
+  // Override specialized return types
+
+  flip(): Map<V, K>;
+
+  filter(predicate: typeof Boolean): Map<K, $NonMaybeType<V>>;
+  filter(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): Map<K, V>;
+
+  partition(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: V, key: K, iter: this) => M,
+    context?: mixed
+  ): Map<K, M>;
+
+  mapKeys<M>(
+    mapper: (key: K, value: V, iter: this) => M,
+    context?: mixed
+  ): Map<M, V>;
+
+  mapEntries<KM, VM>(
+    mapper: (entry: [K, V], index: number, iter: this) => [KM, VM],
+    context?: mixed
+  ): Map<KM, VM>;
+
+  flatMap<KM, VM>(
+    mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+    context?: mixed
+  ): Map<KM, VM>;
+
+  flatten(depth?: number): Map<any, any>;
+  flatten(shallow?: boolean): Map<any, any>;
+}
+
+declare function isOrderedMap(
+  maybeOrderedMap: mixed
+): boolean %checks(maybeOrderedMap instanceof OrderedMap);
+declare class OrderedMap<K, +V>
+  extends Map<K, V>
+  mixins UpdatableInCollection<K, V>
+{
+  static <K, V>(
+    values?: Iterable<[K, V]> | PlainObjInput<K, V>
+  ): OrderedMap<K, V>;
+
+  static isOrderedMap: typeof isOrderedMap;
+
+  size: number;
+
+  set<K_, V_>(key: K_, value: V_): OrderedMap<K | K_, V | V_>;
+  delete(key: K): this;
+  remove(key: K): this;
+  clear(): this;
+
+  update<U>(updater: (value: this) => U): U;
+  update<V_>(key: K, updater: (value: V) => V_): OrderedMap<K, V | V_>;
+  update<V_>(
+    key: K,
+    notSetValue: V_,
+    updater: (value: V) => V_
+  ): OrderedMap<K, V | V_>;
+
+  merge<K_, V_>(
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): OrderedMap<K | K_, V | V_>;
+  concat<K_, V_>(
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): OrderedMap<K | K_, V | V_>;
+
+  mergeWith<K_, W, X>(
+    merger: (oldVal: V, newVal: W, key: K) => X,
+    ...collections: (Iterable<[K_, W]> | PlainObjInput<K_, W>)[]
+  ): OrderedMap<K | K_, V | W | X>;
+
+  mergeDeep<K_, V_>(
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): OrderedMap<K | K_, V | V_>;
+
+  mergeDeepWith<K_, V_>(
+    merger: (oldVal: any, newVal: any, key: any) => mixed,
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): OrderedMap<K | K_, V | V_>;
+
+  mergeIn(
+    keyPath: Iterable<mixed>,
+    ...collections: (Iterable<mixed> | PlainObjInput<mixed, mixed>)[]
+  ): this;
+  mergeDeepIn(
+    keyPath: Iterable<mixed>,
+    ...collections: (Iterable<mixed> | PlainObjInput<mixed, mixed>)[]
+  ): this;
+
+  withMutations(mutator: (mutable: this) => mixed): this;
+  asMutable(): this;
+  wasAltered(): boolean;
+  asImmutable(): this;
+
+  // Override specialized return types
+
+  flip(): OrderedMap<V, K>;
+
+  filter(predicate: typeof Boolean): OrderedMap<K, $NonMaybeType<V>>;
+  filter(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): OrderedMap<K, V>;
+
+  partition(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: V, key: K, iter: this) => M,
+    context?: mixed
+  ): OrderedMap<K, M>;
+
+  mapKeys<M>(
+    mapper: (key: K, value: V, iter: this) => M,
+    context?: mixed
+  ): OrderedMap<M, V>;
+
+  mapEntries<KM, VM>(
+    mapper: (entry: [K, V], index: number, iter: this) => [KM, VM],
+    context?: mixed
+  ): OrderedMap<KM, VM>;
+
+  flatMap<KM, VM>(
+    mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+    context?: mixed
+  ): OrderedMap<KM, VM>;
+
+  flatten(depth?: number): OrderedMap<any, any>;
+  flatten(shallow?: boolean): OrderedMap<any, any>;
+}
+
+declare function isSet(maybeSet: mixed): boolean %checks(maybeSet instanceof
+  Set);
+declare class Set<+T> extends SetCollection<T> {
+  static <T>(values?: Iterable<T>): Set<T>;
+
+  static of<T>(...values: T[]): Set<T>;
+  static fromKeys<T>(
+    values: Iterable<[T, mixed]> | PlainObjInput<T, mixed>
+  ): Set<T>;
+
+  static intersect<T>(sets: Iterable<Iterable<T>>): Set<T>;
+  static union<T>(sets: Iterable<Iterable<T>>): Set<T>;
+
+  static isSet: typeof isSet;
+
+  size: number;
+
+  add<U>(value: U): Set<T | U>;
+  delete(value: T): this;
+  remove(value: T): this;
+  clear(): this;
+  union<U>(...collections: Iterable<U>[]): Set<T | U>;
+  merge<U>(...collections: Iterable<U>[]): Set<T | U>;
+  concat<U>(...collections: Iterable<U>[]): Set<T | U>;
+  intersect<U>(...collections: Iterable<U>[]): Set<T & U>;
+  subtract(...collections: Iterable<mixed>[]): this;
+
+  withMutations(mutator: (mutable: this) => mixed): this;
+  asMutable(): this;
+  wasAltered(): boolean;
+  asImmutable(): this;
+
+  // Override specialized return types
+
+  filter(predicate: typeof Boolean): Set<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): Set<T>;
+
+  partition(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: T, value: T, iter: this) => M,
+    context?: mixed
+  ): Set<M>;
+
+  flatMap<M>(
+    mapper: (value: T, value: T, iter: this) => Iterable<M>,
+    context?: mixed
+  ): Set<M>;
+
+  flatten(depth?: number): Set<any>;
+  flatten(shallow?: boolean): Set<any>;
+}
+
+// Overrides except for `isOrderedSet` are for specialized return types
+declare function isOrderedSet(
+  maybeOrderedSet: mixed
+): boolean %checks(maybeOrderedSet instanceof OrderedSet);
+declare class OrderedSet<+T> extends Set<T> {
+  static <T>(values?: Iterable<T>): OrderedSet<T>;
+
+  static of<T>(...values: T[]): OrderedSet<T>;
+  static fromKeys<T>(
+    values: Iterable<[T, mixed]> | PlainObjInput<T, mixed>
+  ): OrderedSet<T>;
+
+  static isOrderedSet: typeof isOrderedSet;
+
+  size: number;
+
+  add<U>(value: U): OrderedSet<T | U>;
+  union<U>(...collections: Iterable<U>[]): OrderedSet<T | U>;
+  merge<U>(...collections: Iterable<U>[]): OrderedSet<T | U>;
+  concat<U>(...collections: Iterable<U>[]): OrderedSet<T | U>;
+  intersect<U>(...collections: Iterable<U>[]): OrderedSet<T & U>;
+
+  filter(predicate: typeof Boolean): OrderedSet<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): OrderedSet<T>;
+
+  partition(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: T, value: T, iter: this) => M,
+    context?: mixed
+  ): OrderedSet<M>;
+
+  flatMap<M>(
+    mapper: (value: T, value: T, iter: this) => Iterable<M>,
+    context?: mixed
+  ): OrderedSet<M>;
+
+  flatten(depth?: number): OrderedSet<any>;
+  flatten(shallow?: boolean): OrderedSet<any>;
+
+  zip<A>(a: Iterable<A>, ..._: []): OrderedSet<[T, A]>;
+  zip<A, B>(a: Iterable<A>, b: Iterable<B>, ..._: []): OrderedSet<[T, A, B]>;
+  zip<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): OrderedSet<[T, A, B, C]>;
+  zip<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): OrderedSet<[T, A, B, C, D]>;
+  zip<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): OrderedSet<[T, A, B, C, D, E]>;
+
+  zipAll<A>(a: Iterable<A>, ..._: []): OrderedSet<[T | void, A | void]>;
+  zipAll<A, B>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): OrderedSet<[T | void, A | void, B | void]>;
+  zipAll<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): OrderedSet<[T | void, A | void, B | void, C | void]>;
+  zipAll<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): OrderedSet<[T | void, A | void, B | void, C | void, D | void]>;
+  zipAll<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): OrderedSet<[T | void, A | void, B | void, C | void, D | void, E | void]>;
+
+  zipWith<A, R>(
+    zipper: (value: T, a: A) => R,
+    a: Iterable<A>,
+    ..._: []
+  ): OrderedSet<R>;
+  zipWith<A, B, R>(
+    zipper: (value: T, a: A, b: B) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): OrderedSet<R>;
+  zipWith<A, B, C, R>(
+    zipper: (value: T, a: A, b: B, c: C) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): OrderedSet<R>;
+  zipWith<A, B, C, D, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): OrderedSet<R>;
+  zipWith<A, B, C, D, E, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D, e: E) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): OrderedSet<R>;
+}
+
+declare function isStack(
+  maybeStack: mixed
+): boolean %checks(maybeStack instanceof Stack);
+declare class Stack<+T> extends IndexedCollection<T> {
+  static <T>(collection?: Iterable<T>): Stack<T>;
+
+  static isStack(maybeStack: mixed): boolean;
+  static of<T>(...values: T[]): Stack<T>;
+
+  static isStack: typeof isStack;
+
+  size: number;
+
+  peek(): T;
+  clear(): this;
+  unshift<U>(...values: U[]): Stack<T | U>;
+  unshiftAll<U>(iter: Iterable<U>): Stack<T | U>;
+  shift(): this;
+  push<U>(...values: U[]): Stack<T | U>;
+  pushAll<U>(iter: Iterable<U>): Stack<T | U>;
+  pop(): this;
+
+  withMutations(mutator: (mutable: this) => mixed): this;
+  asMutable(): this;
+  wasAltered(): boolean;
+  asImmutable(): this;
+
+  // Override specialized return types
+
+  concat<C>(...iters: Array<Iterable<C> | C>): Stack<T | C>;
+
+  filter(predicate: typeof Boolean): Stack<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): Stack<T>;
+
+  map<M>(
+    mapper: (value: T, index: number, iter: this) => M,
+    context?: mixed
+  ): Stack<M>;
+
+  flatMap<M>(
+    mapper: (value: T, index: number, iter: this) => Iterable<M>,
+    context?: mixed
+  ): Stack<M>;
+
+  flatten(depth?: number): Stack<any>;
+  flatten(shallow?: boolean): Stack<any>;
+
+  zip<A>(a: Iterable<A>, ..._: []): Stack<[T, A]>;
+  zip<A, B>(a: Iterable<A>, b: Iterable<B>, ..._: []): Stack<[T, A, B]>;
+  zip<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): Stack<[T, A, B, C]>;
+  zip<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): Stack<[T, A, B, C, D]>;
+  zip<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): Stack<[T, A, B, C, D, E]>;
+
+  zipAll<A>(a: Iterable<A>, ..._: []): Stack<[T | void, A | void]>;
+  zipAll<A, B>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): Stack<[T | void, A | void, B | void]>;
+  zipAll<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): Stack<[T | void, A | void, B | void, C | void]>;
+  zipAll<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): Stack<[T | void, A | void, B | void, C | void, D | void]>;
+  zipAll<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): Stack<[T | void, A | void, B | void, C | void, D | void, E | void]>;
+
+  zipWith<A, R>(
+    zipper: (value: T, a: A) => R,
+    a: Iterable<A>,
+    ..._: []
+  ): Stack<R>;
+  zipWith<A, B, R>(
+    zipper: (value: T, a: A, b: B) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): Stack<R>;
+  zipWith<A, B, C, R>(
+    zipper: (value: T, a: A, b: B, c: C) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): Stack<R>;
+  zipWith<A, B, C, D, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): Stack<R>;
+  zipWith<A, B, C, D, E, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D, e: E) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): Stack<R>;
+}
+
+declare function Range(
+  start?: number,
+  end?: number,
+  step?: number
+): IndexedSeq<number>;
+declare function Repeat<T>(value: T, times?: number): IndexedSeq<T>;
+
+// The type of a Record factory function.
+type RecordFactory<Values: Object> = Class<RecordInstance<Values>>;
+
+// The type of runtime Record instances.
+type RecordOf<Values: Object> = RecordInstance<Values> & $ReadOnly<Values>;
+
+// The values of a Record instance.
+type _RecordValues<T, R: RecordInstance<T> | T> = R;
+type RecordValues<R> = _RecordValues<*, R>;
+
+declare function isRecord(
+  maybeRecord: any
+): boolean %checks(maybeRecord instanceof RecordInstance);
+declare class Record {
+  static <Values: Object>(spec: Values, name?: string): typeof RecordInstance;
+  constructor<Values: Object>(
+    spec: Values,
+    name?: string
+  ): typeof RecordInstance;
+
+  static isRecord: typeof isRecord;
+
+  static getDescriptiveName(record: RecordInstance<any>): string;
+}
+
+declare class RecordInstance<T: Object = Object> {
+  static (values?: Iterable<[$Keys<T>, $ValOf<T>]> | $Shape<T>): RecordOf<T>;
+  // Note: a constructor can only create an instance of RecordInstance<T>,
+  // it's encouraged to not use `new` when creating Records.
+  constructor(values?: Iterable<[$Keys<T>, $ValOf<T>]> | $Shape<T>): void;
+
+  size: number;
+
+  has(key: string): boolean;
+
+  get<K: $Keys<T>>(key: K, ..._: []): $ElementType<T, K>;
+  get<K: $Keys<T>, NSV>(key: K, notSetValue: NSV): $ElementType<T, K> | NSV;
+
+  hasIn(keyPath: Iterable<mixed>): boolean;
+
+  getIn(keyPath: [], notSetValue?: mixed): this & $ReadOnly<T>;
+  getIn<K: $Keys<T>>(keyPath: [K], notSetValue?: mixed): $ElementType<T, K>;
+  getIn<NSV, K: $Keys<T>, K2: $KeyOf<$ValOf<T, K>>>(
+    keyPath: [K, K2],
+    notSetValue: NSV
+  ): $ValOf<$ValOf<T, K>, K2> | NSV;
+  getIn<
+    NSV,
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>
+  >(
+    keyPath: [K, K2, K3],
+    notSetValue: NSV
+  ): $ValOf<$ValOf<$ValOf<T, K>, K2>, K3> | NSV;
+  getIn<
+    NSV,
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>
+  >(
+    keyPath: [K, K2, K3, K4],
+    notSetValue: NSV
+  ): $ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4> | NSV;
+  getIn<
+    NSV,
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>>
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    notSetValue: NSV
+  ): $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>, K5> | NSV;
+
+  equals(other: any): boolean;
+  hashCode(): number;
+
+  set<K: $Keys<T>>(key: K, value: $ElementType<T, K>): this & $ReadOnly<T>;
+  update<K: $Keys<T>>(
+    key: K,
+    updater: (value: $ElementType<T, K>) => $ElementType<T, K>
+  ): this & $ReadOnly<T>;
+  merge(
+    ...collections: Array<Iterable<[$Keys<T>, $ValOf<T>]> | $Shape<T>>
+  ): this & $ReadOnly<T>;
+  mergeDeep(
+    ...collections: Array<Iterable<[$Keys<T>, $ValOf<T>]> | $Shape<T>>
+  ): this & $ReadOnly<T>;
+
+  mergeWith(
+    merger: (oldVal: $ValOf<T>, newVal: $ValOf<T>, key: $Keys<T>) => $ValOf<T>,
+    ...collections: Array<Iterable<[$Keys<T>, $ValOf<T>]> | $Shape<T>>
+  ): this & $ReadOnly<T>;
+  mergeDeepWith(
+    merger: (oldVal: any, newVal: any, key: any) => any,
+    ...collections: Array<Iterable<[$Keys<T>, $ValOf<T>]> | $Shape<T>>
+  ): this & $ReadOnly<T>;
+
+  delete<K: $Keys<T>>(key: K): this & $ReadOnly<T>;
+  remove<K: $Keys<T>>(key: K): this & $ReadOnly<T>;
+  clear(): this & $ReadOnly<T>;
+
+  setIn<S>(keyPath: [], value: S): S;
+  setIn<K: $Keys<T>, S: $ValOf<T, K>>(
+    keyPath: [K],
+    value: S
+  ): this & $ReadOnly<T>;
+  setIn<K: $Keys<T>, K2: $KeyOf<$ValOf<T, K>>, S: $ValOf<$ValOf<T, K>, K2>>(
+    keyPath: [K, K2],
+    value: S
+  ): this & $ReadOnly<T>;
+  setIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    S: $ValOf<$ValOf<$ValOf<T, K>, K2>, K3>
+  >(
+    keyPath: [K, K2, K3],
+    value: S
+  ): this & $ReadOnly<T>;
+  setIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>
+  >(
+    keyPath: [K, K2, K3, K4],
+    value: S
+  ): this & $ReadOnly<T>;
+  setIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>, K5>
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    value: S
+  ): this & $ReadOnly<T>;
+
+  deleteIn(keyPath: []): void;
+  deleteIn<K: $Keys<T>>(keyPath: [K]): this & $ReadOnly<T>;
+  deleteIn<K: $Keys<T>, K2: $KeyOf<$ValOf<T, K>>>(
+    keyPath: [K, K2]
+  ): this & $ReadOnly<T>;
+  deleteIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>
+  >(
+    keyPath: [K, K2, K3]
+  ): this & $ReadOnly<T>;
+  deleteIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>
+  >(
+    keyPath: [K, K2, K3, K4]
+  ): this & $ReadOnly<T>;
+  deleteIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>>
+  >(
+    keyPath: [K, K2, K3, K4, K5]
+  ): this & $ReadOnly<T>;
+
+  removeIn(keyPath: []): void;
+  removeIn<K: $Keys<T>>(keyPath: [K]): this & $ReadOnly<T>;
+  removeIn<K: $Keys<T>, K2: $KeyOf<$ValOf<T, K>>>(
+    keyPath: [K, K2]
+  ): this & $ReadOnly<T>;
+  removeIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>
+  >(
+    keyPath: [K, K2, K3]
+  ): this & $ReadOnly<T>;
+  removeIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>
+  >(
+    keyPath: [K, K2, K3, K4]
+  ): this & $ReadOnly<T>;
+  removeIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>>
+  >(
+    keyPath: [K, K2, K3, K4, K5]
+  ): this & $ReadOnly<T>;
+
+  updateIn<U>(
+    keyPath: [],
+    notSetValue: mixed,
+    updater: (value: this & T) => U
+  ): U;
+  updateIn<U>(keyPath: [], updater: (value: this & T) => U): U;
+  updateIn<NSV, K: $Keys<T>, S: $ValOf<T, K>>(
+    keyPath: [K],
+    notSetValue: NSV,
+    updater: (value: $ValOf<T, K>) => S
+  ): this & $ReadOnly<T>;
+  updateIn<K: $Keys<T>, S: $ValOf<T, K>>(
+    keyPath: [K],
+    updater: (value: $ValOf<T, K>) => S
+  ): this & $ReadOnly<T>;
+  updateIn<
+    NSV,
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    S: $ValOf<$ValOf<T, K>, K2>
+  >(
+    keyPath: [K, K2],
+    notSetValue: NSV,
+    updater: (value: $ValOf<$ValOf<T, K>, K2> | NSV) => S
+  ): this & $ReadOnly<T>;
+  updateIn<K: $Keys<T>, K2: $KeyOf<$ValOf<T, K>>, S: $ValOf<$ValOf<T, K>, K2>>(
+    keyPath: [K, K2],
+    updater: (value: $ValOf<$ValOf<T, K>, K2>) => S
+  ): this & $ReadOnly<T>;
+  updateIn<
+    NSV,
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    S: $ValOf<$ValOf<$ValOf<T, K>, K2>, K3>
+  >(
+    keyPath: [K, K2, K3],
+    notSetValue: NSV,
+    updater: (value: $ValOf<$ValOf<$ValOf<T, K>, K2>, K3> | NSV) => S
+  ): this & $ReadOnly<T>;
+  updateIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    S: $ValOf<$ValOf<$ValOf<T, K>, K2>, K3>
+  >(
+    keyPath: [K, K2, K3],
+    updater: (value: $ValOf<$ValOf<$ValOf<T, K>, K2>, K3>) => S
+  ): this & $ReadOnly<T>;
+  updateIn<
+    NSV,
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>
+  >(
+    keyPath: [K, K2, K3, K4],
+    notSetValue: NSV,
+    updater: (
+      value: $ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4> | NSV
+    ) => S
+  ): this & $ReadOnly<T>;
+  updateIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>
+  >(
+    keyPath: [K, K2, K3, K4],
+    updater: (value: $ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>) => S
+  ): this & $ReadOnly<T>;
+  updateIn<
+    NSV,
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>, K5>
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    notSetValue: NSV,
+    updater: (
+      value: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>, K5> | NSV
+    ) => S
+  ): this & $ReadOnly<T>;
+  updateIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>, K5>
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    updater: (
+      value: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>, K5>
+    ) => S
+  ): this & $ReadOnly<T>;
+
+  mergeIn(
+    keyPath: Iterable<mixed>,
+    ...collections: Array<any>
+  ): this & $ReadOnly<T>;
+  mergeDeepIn(
+    keyPath: Iterable<mixed>,
+    ...collections: Array<any>
+  ): this & $ReadOnly<T>;
+
+  toSeq(): KeyedSeq<$Keys<T>, any>;
+
+  toJS(): { [key: $Keys<T>]: mixed };
+  toJSON(): T;
+  toObject(): T;
+
+  withMutations(mutator: (mutable: this & T) => mixed): this & $ReadOnly<T>;
+  asMutable(): this & $ReadOnly<T>;
+  wasAltered(): boolean;
+  asImmutable(): this & $ReadOnly<T>;
+
+  @@iterator(): Iterator<[$Keys<T>, $ValOf<T>]>;
+}
+
+declare function fromJS(
+  jsValue: mixed,
+  reviver?: (
+    key: string | number,
+    sequence: KeyedCollection<string, mixed> | IndexedCollection<mixed>,
+    path?: Array<string | number>
+  ) => mixed
+): Collection<mixed, mixed>;
+
+declare function is(first: mixed, second: mixed): boolean;
+declare function hash(value: mixed): number;
+
+declare function get<C: Object, K: $Keys<C>>(
+  collection: C,
+  key: K,
+  notSetValue: mixed
+): $ValOf<C, K>;
+declare function get<C, K: $KeyOf<C>, NSV>(
+  collection: C,
+  key: K,
+  notSetValue: NSV
+): $ValOf<C, K> | NSV;
+
+declare function has(collection: Object, key: mixed): boolean;
+declare function remove<C>(collection: C, key: $KeyOf<C>): C;
+declare function set<C, K: $KeyOf<C>, V: $ValOf<C, K>>(
+  collection: C,
+  key: K,
+  value: V
+): C;
+declare function update<C, K: $KeyOf<C>, V: $ValOf<C, K>, NSV>(
+  collection: C,
+  key: K,
+  notSetValue: NSV,
+  updater: ($ValOf<C, K> | NSV) => V
+): C;
+declare function update<C, K: $KeyOf<C>, V: $ValOf<C, K>>(
+  collection: C,
+  key: K,
+  updater: ($ValOf<C, K>) => V
+): C;
+
+declare function getIn<C>(collection: C, keyPath: [], notSetValue?: mixed): C;
+declare function getIn<C, K: $KeyOf<C>, NSV>(
+  collection: C,
+  keyPath: [K],
+  notSetValue: NSV
+): $ValOf<C, K> | NSV;
+declare function getIn<C, K: $KeyOf<C>, K2: $KeyOf<$ValOf<C, K>>, NSV>(
+  collection: C,
+  keyPath: [K, K2],
+  notSetValue: NSV
+): $ValOf<$ValOf<C, K>, K2> | NSV;
+declare function getIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  NSV
+>(
+  collection: C,
+  keyPath: [K, K2, K3],
+  notSetValue: NSV
+): $ValOf<$ValOf<$ValOf<C, K>, K2>, K3> | NSV;
+declare function getIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  NSV
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4],
+  notSetValue: NSV
+): $ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4> | NSV;
+declare function getIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>>,
+  NSV
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4, K5],
+  notSetValue: NSV
+): $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>, K5> | NSV;
+
+declare function hasIn(collection: Object, keyPath: Iterable<mixed>): boolean;
+
+declare function removeIn<C>(collection: C, keyPath: []): void;
+declare function removeIn<C, K: $KeyOf<C>>(collection: C, keyPath: [K]): C;
+declare function removeIn<C, K: $KeyOf<C>, K2: $KeyOf<$ValOf<C, K>>>(
+  collection: C,
+  keyPath: [K, K2]
+): C;
+declare function removeIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>
+>(
+  collection: C,
+  keyPath: [K, K2, K3]
+): C;
+declare function removeIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4]
+): C;
+declare function removeIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>>
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4, K5]
+): C;
+
+declare function setIn<S>(collection: Object, keyPath: [], value: S): S;
+declare function setIn<C, K: $KeyOf<C>, S: $ValOf<C, K>>(
+  collection: C,
+  keyPath: [K],
+  value: S
+): C;
+declare function setIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  S: $ValOf<$ValOf<C, K>, K2>
+>(
+  collection: C,
+  keyPath: [K, K2],
+  value: S
+): C;
+declare function setIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  S: $ValOf<$ValOf<$ValOf<C, K>, K2>, K3>
+>(
+  collection: C,
+  keyPath: [K, K2, K3],
+  value: S
+): C;
+declare function setIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  S: $ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4],
+  value: S
+): C;
+declare function setIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>>,
+  S: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>, K5>
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4, K5],
+  value: S
+): C;
+
+declare function updateIn<C, S>(
+  collection: C,
+  keyPath: [],
+  notSetValue: mixed,
+  updater: (value: C) => S
+): S;
+declare function updateIn<C, S>(
+  collection: C,
+  keyPath: [],
+  updater: (value: C) => S
+): S;
+declare function updateIn<C, K: $KeyOf<C>, S: $ValOf<C, K>, NSV>(
+  collection: C,
+  keyPath: [K],
+  notSetValue: NSV,
+  updater: (value: $ValOf<C, K> | NSV) => S
+): C;
+declare function updateIn<C, K: $KeyOf<C>, S: $ValOf<C, K>>(
+  collection: C,
+  keyPath: [K],
+  updater: (value: $ValOf<C, K>) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  S: $ValOf<$ValOf<C, K>, K2>,
+  NSV
+>(
+  collection: C,
+  keyPath: [K, K2],
+  notSetValue: NSV,
+  updater: (value: $ValOf<$ValOf<C, K>, K2> | NSV) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  S: $ValOf<$ValOf<C, K>, K2>
+>(
+  collection: C,
+  keyPath: [K, K2],
+  updater: (value: $ValOf<$ValOf<C, K>, K2>) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  S: $ValOf<$ValOf<$ValOf<C, K>, K2>, K3>,
+  NSV
+>(
+  collection: C,
+  keyPath: [K, K2, K3],
+  notSetValue: NSV,
+  updater: (value: $ValOf<$ValOf<$ValOf<C, K>, K2>, K3> | NSV) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  S: $ValOf<$ValOf<$ValOf<C, K>, K2>, K3>
+>(
+  collection: C,
+  keyPath: [K, K2, K3],
+  updater: (value: $ValOf<$ValOf<$ValOf<C, K>, K2>, K3>) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  S: $ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>,
+  NSV
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4],
+  notSetValue: NSV,
+  updater: (value: $ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4> | NSV) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  S: $ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4],
+  updater: (value: $ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>>,
+  S: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>, K5>,
+  NSV
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4, K5],
+  notSetValue: NSV,
+  updater: (
+    value: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>, K5> | NSV
+  ) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>>,
+  S: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>, K5>
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4, K5],
+  updater: (
+    value: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>, K5>
+  ) => S
+): C;
+
+declare function merge<C>(
+  collection: C,
+  ...collections: Array<
+    | $IterableOf<C>
+    | $Shape<RecordValues<C>>
+    | PlainObjInput<$KeyOf<C>, $ValOf<C>>
+  >
+): C;
+declare function mergeWith<C>(
+  merger: (oldVal: $ValOf<C>, newVal: $ValOf<C>, key: $KeyOf<C>) => $ValOf<C>,
+  collection: C,
+  ...collections: Array<
+    | $IterableOf<C>
+    | $Shape<RecordValues<C>>
+    | PlainObjInput<$KeyOf<C>, $ValOf<C>>
+  >
+): C;
+declare function mergeDeep<C>(
+  collection: C,
+  ...collections: Array<
+    | $IterableOf<C>
+    | $Shape<RecordValues<C>>
+    | PlainObjInput<$KeyOf<C>, $ValOf<C>>
+  >
+): C;
+declare function mergeDeepWith<C>(
+  merger: (oldVal: any, newVal: any, key: any) => mixed,
+  collection: C,
+  ...collections: Array<
+    | $IterableOf<C>
+    | $Shape<RecordValues<C>>
+    | PlainObjInput<$KeyOf<C>, $ValOf<C>>
+  >
+): C;
+
+export {
+  Collection,
+  Seq,
+  List,
+  Map,
+  OrderedMap,
+  OrderedSet,
+  Range,
+  Repeat,
+  Record,
+  Set,
+  Stack,
+  fromJS,
+  is,
+  hash,
+  isImmutable,
+  isCollection,
+  isKeyed,
+  isIndexed,
+  isAssociative,
+  isOrdered,
+  isRecord,
+  isValueObject,
+  get,
+  has,
+  remove,
+  set,
+  update,
+  getIn,
+  hasIn,
+  removeIn,
+  setIn,
+  updateIn,
+  merge,
+  mergeWith,
+  mergeDeep,
+  mergeDeepWith,
+};
+
+export default {
+  Collection,
+  Seq,
+
+  List,
+  Map,
+  OrderedMap,
+  OrderedSet,
+  PairSorting,
+  Range,
+  Repeat,
+  Record,
+  Set,
+  Stack,
+
+  fromJS,
+  is,
+  hash,
+
+  isImmutable,
+  isCollection,
+  isKeyed,
+  isIndexed,
+  isAssociative,
+  isOrdered,
+  isRecord,
+  isValueObject,
+
+  get,
+  has,
+  remove,
+  set,
+  update,
+  getIn,
+  hasIn,
+  removeIn,
+  setIn,
+  updateIn,
+  merge,
+  mergeWith,
+  mergeDeep,
+  mergeDeepWith,
+};
+
+export type {
+  Comparator,
+  KeyedCollection,
+  IndexedCollection,
+  SetCollection,
+  KeyedSeq,
+  IndexedSeq,
+  SetSeq,
+  RecordFactory,
+  RecordOf,
+  RecordInstance,
+  ValueObject,
+  $KeyOf,
+  $ValOf,
+};
Index: imaps-frontend/node_modules/immutable/dist/immutable.min.js
===================================================================
--- imaps-frontend/node_modules/immutable/dist/immutable.min.js	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
+++ imaps-frontend/node_modules/immutable/dist/immutable.min.js	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
@@ -0,0 +1,25 @@
+/**
+ * @license
+ * MIT License
+ * 
+ * Copyright (c) 2014-present, Lee Byron and other contributors.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).Immutable={})}(this,(function(t){"use strict";var e="delete",r=5,n=1<<r,i=n-1,o={};function u(t){t&&(t.value=!0)}function s(){}function a(t){return void 0===t.size&&(t.size=t.__iterate(f)),t.size}function c(t,e){if("number"!=typeof e){var r=e>>>0;if(""+r!==e||4294967295===r)return NaN;e=r}return e<0?a(t)+e:e}function f(){return!0}function h(t,e,r){return(0===t&&!v(t)||void 0!==r&&t<=-r)&&(void 0===e||void 0!==r&&e>=r)}function p(t,e){return l(t,e,0)}function _(t,e){return l(t,e,e)}function l(t,e,r){return void 0===t?r:v(t)?e===1/0?e:0|Math.max(0,e+t):void 0===e||e===t?t:0|Math.min(e,t)}function v(t){return t<0||0===t&&1/t==-1/0}var y="@@__IMMUTABLE_ITERABLE__@@";function d(t){return Boolean(t&&t[y])}var g="@@__IMMUTABLE_KEYED__@@";function w(t){return Boolean(t&&t[g])}var m="@@__IMMUTABLE_INDEXED__@@";function z(t){return Boolean(t&&t[m])}function S(t){return w(t)||z(t)}var b=function(t){return d(t)?t:X(t)},I=function(t){function e(t){return w(t)?t:F(t)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e}(b),O=function(t){function e(t){return z(t)?t:G(t)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e}(b),E=function(t){function e(t){return d(t)&&!S(t)?t:Z(t)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e}(b);b.Keyed=I,b.Indexed=O,b.Set=E;var q="@@__IMMUTABLE_SEQ__@@";function j(t){return Boolean(t&&t[q])}var M="@@__IMMUTABLE_RECORD__@@";function D(t){return Boolean(t&&t[M])}function x(t){return d(t)||D(t)}var A="@@__IMMUTABLE_ORDERED__@@";function k(t){return Boolean(t&&t[A])}var R=0,U=1,T=2,B="function"==typeof Symbol&&Symbol.iterator,K="@@iterator",L=B||K,C=function(t){this.next=t};function P(t,e,r,n){var i=0===t?e:1===t?r:[e,r];return n?n.value=i:n={value:i,done:!1},n}function W(){return{value:void 0,done:!0}}function N(t){return!!Array.isArray(t)||!!V(t)}function H(t){return t&&"function"==typeof t.next}function J(t){var e=V(t);return e&&e.call(t)}function V(t){var e=t&&(B&&t[B]||t[K]);if("function"==typeof e)return e}C.prototype.toString=function(){return"[Iterator]"},C.KEYS=R,C.VALUES=U,C.ENTRIES=T,C.prototype.inspect=C.prototype.toSource=function(){return this.toString()},C.prototype[L]=function(){return this};var Y=Object.prototype.hasOwnProperty;function Q(t){return!(!Array.isArray(t)&&"string"!=typeof t)||t&&"object"==typeof t&&Number.isInteger(t.length)&&t.length>=0&&(0===t.length?1===Object.keys(t).length:t.hasOwnProperty(t.length-1))}var X=function(t){function e(t){return null==t?nt():x(t)?t.toSeq():function(t){var e=ut(t);if(e)return(n=V(r=t))&&n===r.entries?e.fromEntrySeq():function(t){var e=V(t);return e&&e===t.keys}(t)?e.toSetSeq():e;var r,n;if("object"==typeof t)return new tt(t);throw new TypeError("Expected Array or collection object of values, or keyed object: "+t)}(t)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.toSeq=function(){return this},e.prototype.toString=function(){return this.__toString("Seq {","}")},e.prototype.cacheResult=function(){return!this._cache&&this.__iterateUncached&&(this._cache=this.entrySeq().toArray(),this.size=this._cache.length),this},e.prototype.__iterate=function(t,e){var r=this._cache;if(r){for(var n=r.length,i=0;i!==n;){var o=r[e?n-++i:i++];if(!1===t(o[1],o[0],this))break}return i}return this.__iterateUncached(t,e)},e.prototype.__iterator=function(t,e){var r=this._cache;if(r){var n=r.length,i=0;return new C((function(){if(i===n)return{value:void 0,done:!0};var o=r[e?n-++i:i++];return P(t,o[0],o[1])}))}return this.__iteratorUncached(t,e)},e}(b),F=function(t){function e(t){return null==t?nt().toKeyedSeq():d(t)?w(t)?t.toSeq():t.fromEntrySeq():D(t)?t.toSeq():it(t)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.toKeyedSeq=function(){return this},e}(X),G=function(t){function e(t){return null==t?nt():d(t)?w(t)?t.entrySeq():t.toIndexedSeq():D(t)?t.toSeq().entrySeq():ot(t)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.of=function(){return e(arguments)},e.prototype.toIndexedSeq=function(){return this},e.prototype.toString=function(){return this.__toString("Seq [","]")},e}(X),Z=function(t){function e(t){return(d(t)&&!S(t)?t:G(t)).toSetSeq()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.of=function(){return e(arguments)},e.prototype.toSetSeq=function(){return this},e}(X);X.isSeq=j,X.Keyed=F,X.Set=Z,X.Indexed=G,X.prototype[q]=!0;var $=function(t){function e(t){this._array=t,this.size=t.length}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.get=function(t,e){return this.has(t)?this._array[c(this,t)]:e},e.prototype.__iterate=function(t,e){for(var r=this._array,n=r.length,i=0;i!==n;){var o=e?n-++i:i++;if(!1===t(r[o],o,this))break}return i},e.prototype.__iterator=function(t,e){var r=this._array,n=r.length,i=0;return new C((function(){if(i===n)return{value:void 0,done:!0};var o=e?n-++i:i++;return P(t,o,r[o])}))},e}(G),tt=function(t){function e(t){var e=Object.keys(t).concat(Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(t):[]);this._object=t,this._keys=e,this.size=e.length}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.get=function(t,e){return void 0===e||this.has(t)?this._object[t]:e},e.prototype.has=function(t){return Y.call(this._object,t)},e.prototype.__iterate=function(t,e){for(var r=this._object,n=this._keys,i=n.length,o=0;o!==i;){var u=n[e?i-++o:o++];if(!1===t(r[u],u,this))break}return o},e.prototype.__iterator=function(t,e){var r=this._object,n=this._keys,i=n.length,o=0;return new C((function(){if(o===i)return{value:void 0,done:!0};var u=n[e?i-++o:o++];return P(t,u,r[u])}))},e}(F);tt.prototype[A]=!0;var et,rt=function(t){function e(t){this._collection=t,this.size=t.length||t.size}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.__iterateUncached=function(t,e){if(e)return this.cacheResult().__iterate(t,e);var r=J(this._collection),n=0;if(H(r))for(var i;!(i=r.next()).done&&!1!==t(i.value,n++,this););return n},e.prototype.__iteratorUncached=function(t,e){if(e)return this.cacheResult().__iterator(t,e);var r=J(this._collection);if(!H(r))return new C(W);var n=0;return new C((function(){var e=r.next();return e.done?e:P(t,n++,e.value)}))},e}(G);function nt(){return et||(et=new $([]))}function it(t){var e=ut(t);if(e)return e.fromEntrySeq();if("object"==typeof t)return new tt(t);throw new TypeError("Expected Array or collection object of [k, v] entries, or keyed object: "+t)}function ot(t){var e=ut(t);if(e)return e;throw new TypeError("Expected Array or collection object of values: "+t)}function ut(t){return Q(t)?new $(t):N(t)?new rt(t):void 0}var st="@@__IMMUTABLE_MAP__@@";function at(t){return Boolean(t&&t[st])}function ct(t){return at(t)&&k(t)}function ft(t){return Boolean(t&&"function"==typeof t.equals&&"function"==typeof t.hashCode)}function ht(t,e){if(t===e||t!=t&&e!=e)return!0;if(!t||!e)return!1;if("function"==typeof t.valueOf&&"function"==typeof e.valueOf){if((t=t.valueOf())===(e=e.valueOf())||t!=t&&e!=e)return!0;if(!t||!e)return!1}return!!(ft(t)&&ft(e)&&t.equals(e))}var pt="function"==typeof Math.imul&&-2===Math.imul(4294967295,2)?Math.imul:function(t,e){var r=65535&(t|=0),n=65535&(e|=0);return r*n+((t>>>16)*n+r*(e>>>16)<<16>>>0)|0};function _t(t){return t>>>1&1073741824|3221225471&t}var lt=Object.prototype.valueOf;function vt(t){if(null==t)return yt(t);if("function"==typeof t.hashCode)return _t(t.hashCode(t));var e,r=(e=t).valueOf!==lt&&"function"==typeof e.valueOf?e.valueOf(e):e;if(null==r)return yt(r);switch(typeof r){case"boolean":return r?1108378657:1108378656;case"number":return function(t){if(t!=t||t===1/0)return 0;var e=0|t;e!==t&&(e^=4294967295*t);for(;t>4294967295;)e^=t/=4294967295;return _t(e)}(r);case"string":return r.length>Et?function(t){var e=Mt[t];void 0===e&&(e=dt(t),jt===qt&&(jt=0,Mt={}),jt++,Mt[t]=e);return e}(r):dt(r);case"object":case"function":return function(t){var e;if(St&&void 0!==(e=zt.get(t)))return e;if(e=t[Ot],void 0!==e)return e;if(!wt){if(void 0!==(e=t.propertyIsEnumerable&&t.propertyIsEnumerable[Ot]))return e;if(void 0!==(e=function(t){if(t&&t.nodeType>0)switch(t.nodeType){case 1:return t.uniqueID;case 9:return t.documentElement&&t.documentElement.uniqueID}}(t)))return e}if(e=mt(),St)zt.set(t,e);else{if(void 0!==gt&&!1===gt(t))throw new Error("Non-extensible objects are not allowed as keys.");if(wt)Object.defineProperty(t,Ot,{enumerable:!1,configurable:!1,writable:!1,value:e});else if(void 0!==t.propertyIsEnumerable&&t.propertyIsEnumerable===t.constructor.prototype.propertyIsEnumerable)t.propertyIsEnumerable=function(){return this.constructor.prototype.propertyIsEnumerable.apply(this,arguments)},t.propertyIsEnumerable[Ot]=e;else{if(void 0===t.nodeType)throw new Error("Unable to set a non-enumerable property on object.");t[Ot]=e}}return e}(r);case"symbol":return function(t){var e=bt[t];if(void 0!==e)return e;return e=mt(),bt[t]=e,e}(r);default:if("function"==typeof r.toString)return dt(r.toString());throw new Error("Value type "+typeof r+" cannot be hashed.")}}function yt(t){return null===t?1108378658:1108378659}function dt(t){for(var e=0,r=0;r<t.length;r++)e=31*e+t.charCodeAt(r)|0;return _t(e)}var gt=Object.isExtensible,wt=function(){try{return Object.defineProperty({},"@",{}),!0}catch(t){return!1}}();function mt(){var t=++It;return 1073741824&It&&(It=0),t}var zt,St="function"==typeof WeakMap;St&&(zt=new WeakMap);var bt=Object.create(null),It=0,Ot="__immutablehash__";"function"==typeof Symbol&&(Ot=Symbol(Ot));var Et=16,qt=255,jt=0,Mt={},Dt=function(t){function e(t,e){this._iter=t,this._useKeys=e,this.size=t.size}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.get=function(t,e){return this._iter.get(t,e)},e.prototype.has=function(t){return this._iter.has(t)},e.prototype.valueSeq=function(){return this._iter.valueSeq()},e.prototype.reverse=function(){var t=this,e=Tt(this,!0);return this._useKeys||(e.valueSeq=function(){return t._iter.toSeq().reverse()}),e},e.prototype.map=function(t,e){var r=this,n=Ut(this,t,e);return this._useKeys||(n.valueSeq=function(){return r._iter.toSeq().map(t,e)}),n},e.prototype.__iterate=function(t,e){var r=this;return this._iter.__iterate((function(e,n){return t(e,n,r)}),e)},e.prototype.__iterator=function(t,e){return this._iter.__iterator(t,e)},e}(F);Dt.prototype[A]=!0;var xt=function(t){function e(t){this._iter=t,this.size=t.size}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.includes=function(t){return this._iter.includes(t)},e.prototype.__iterate=function(t,e){var r=this,n=0;return e&&a(this),this._iter.__iterate((function(i){return t(i,e?r.size-++n:n++,r)}),e)},e.prototype.__iterator=function(t,e){var r=this,n=this._iter.__iterator(U,e),i=0;return e&&a(this),new C((function(){var o=n.next();return o.done?o:P(t,e?r.size-++i:i++,o.value,o)}))},e}(G),At=function(t){function e(t){this._iter=t,this.size=t.size}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.has=function(t){return this._iter.includes(t)},e.prototype.__iterate=function(t,e){var r=this;return this._iter.__iterate((function(e){return t(e,e,r)}),e)},e.prototype.__iterator=function(t,e){var r=this._iter.__iterator(U,e);return new C((function(){var e=r.next();return e.done?e:P(t,e.value,e.value,e)}))},e}(Z),kt=function(t){function e(t){this._iter=t,this.size=t.size}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.entrySeq=function(){return this._iter.toSeq()},e.prototype.__iterate=function(t,e){var r=this;return this._iter.__iterate((function(e){if(e){Vt(e);var n=d(e);return t(n?e.get(1):e[1],n?e.get(0):e[0],r)}}),e)},e.prototype.__iterator=function(t,e){var r=this._iter.__iterator(U,e);return new C((function(){for(;;){var e=r.next();if(e.done)return e;var n=e.value;if(n){Vt(n);var i=d(n);return P(t,i?n.get(0):n[0],i?n.get(1):n[1],e)}}}))},e}(F);function Rt(t){var e=Qt(t);return e._iter=t,e.size=t.size,e.flip=function(){return t},e.reverse=function(){var e=t.reverse.apply(this);return e.flip=function(){return t.reverse()},e},e.has=function(e){return t.includes(e)},e.includes=function(e){return t.has(e)},e.cacheResult=Xt,e.__iterateUncached=function(e,r){var n=this;return t.__iterate((function(t,r){return!1!==e(r,t,n)}),r)},e.__iteratorUncached=function(e,r){if(e===T){var n=t.__iterator(e,r);return new C((function(){var t=n.next();if(!t.done){var e=t.value[0];t.value[0]=t.value[1],t.value[1]=e}return t}))}return t.__iterator(e===U?R:U,r)},e}function Ut(t,e,r){var n=Qt(t);return n.size=t.size,n.has=function(e){return t.has(e)},n.get=function(n,i){var u=t.get(n,o);return u===o?i:e.call(r,u,n,t)},n.__iterateUncached=function(n,i){var o=this;return t.__iterate((function(t,i,u){return!1!==n(e.call(r,t,i,u),i,o)}),i)},n.__iteratorUncached=function(n,i){var o=t.__iterator(T,i);return new C((function(){var i=o.next();if(i.done)return i;var u=i.value,s=u[0];return P(n,s,e.call(r,u[1],s,t),i)}))},n}function Tt(t,e){var r=this,n=Qt(t);return n._iter=t,n.size=t.size,n.reverse=function(){return t},t.flip&&(n.flip=function(){var e=Rt(t);return e.reverse=function(){return t.flip()},e}),n.get=function(r,n){return t.get(e?r:-1-r,n)},n.has=function(r){return t.has(e?r:-1-r)},n.includes=function(e){return t.includes(e)},n.cacheResult=Xt,n.__iterate=function(r,n){var i=this,o=0;return n&&a(t),t.__iterate((function(t,u){return r(t,e?u:n?i.size-++o:o++,i)}),!n)},n.__iterator=function(n,i){var o=0;i&&a(t);var u=t.__iterator(T,!i);return new C((function(){var t=u.next();if(t.done)return t;var s=t.value;return P(n,e?s[0]:i?r.size-++o:o++,s[1],t)}))},n}function Bt(t,e,r,n){var i=Qt(t);return n&&(i.has=function(n){var i=t.get(n,o);return i!==o&&!!e.call(r,i,n,t)},i.get=function(n,i){var u=t.get(n,o);return u!==o&&e.call(r,u,n,t)?u:i}),i.__iterateUncached=function(i,o){var u=this,s=0;return t.__iterate((function(t,o,a){if(e.call(r,t,o,a))return s++,i(t,n?o:s-1,u)}),o),s},i.__iteratorUncached=function(i,o){var u=t.__iterator(T,o),s=0;return new C((function(){for(;;){var o=u.next();if(o.done)return o;var a=o.value,c=a[0],f=a[1];if(e.call(r,f,c,t))return P(i,n?c:s++,f,o)}}))},i}function Kt(t,e,r,n){var i=t.size;if(h(e,r,i))return t;if(void 0===i&&(e<0||r<0))return Kt(t.toSeq().cacheResult(),e,r,n);var o,u=p(e,i),s=_(r,i)-u;s==s&&(o=s<0?0:s);var a=Qt(t);return a.size=0===o?o:t.size&&o||void 0,!n&&j(t)&&o>=0&&(a.get=function(e,r){return(e=c(this,e))>=0&&e<o?t.get(e+u,r):r}),a.__iterateUncached=function(e,r){var i=this;if(0===o)return 0;if(r)return this.cacheResult().__iterate(e,r);var s=0,a=!0,c=0;return t.__iterate((function(t,r){if(!a||!(a=s++<u))return c++,!1!==e(t,n?r:c-1,i)&&c!==o})),c},a.__iteratorUncached=function(e,r){if(0!==o&&r)return this.cacheResult().__iterator(e,r);if(0===o)return new C(W);var i=t.__iterator(e,r),s=0,a=0;return new C((function(){for(;s++<u;)i.next();if(++a>o)return{value:void 0,done:!0};var t=i.next();return n||e===U||t.done?t:P(e,a-1,e===R?void 0:t.value[1],t)}))},a}function Lt(t,e,r,n){var i=Qt(t);return i.__iterateUncached=function(i,o){var u=this;if(o)return this.cacheResult().__iterate(i,o);var s=!0,a=0;return t.__iterate((function(t,o,c){if(!s||!(s=e.call(r,t,o,c)))return a++,i(t,n?o:a-1,u)})),a},i.__iteratorUncached=function(i,o){var u=this;if(o)return this.cacheResult().__iterator(i,o);var s=t.__iterator(T,o),a=!0,c=0;return new C((function(){var t,o,f;do{if((t=s.next()).done)return n||i===U?t:P(i,c++,i===R?void 0:t.value[1],t);var h=t.value;o=h[0],f=h[1],a&&(a=e.call(r,f,o,u))}while(a);return i===T?t:P(i,o,f,t)}))},i}function Ct(t,e,r){var n=Qt(t);return n.__iterateUncached=function(i,o){if(o)return this.cacheResult().__iterate(i,o);var u=0,s=!1;return function t(a,c){a.__iterate((function(o,a){return(!e||c<e)&&d(o)?t(o,c+1):(u++,!1===i(o,r?a:u-1,n)&&(s=!0)),!s}),o)}(t,0),u},n.__iteratorUncached=function(n,i){if(i)return this.cacheResult().__iterator(n,i);var o=t.__iterator(n,i),u=[],s=0;return new C((function(){for(;o;){var t=o.next();if(!1===t.done){var a=t.value;if(n===T&&(a=a[1]),e&&!(u.length<e)||!d(a))return r?t:P(n,s++,a,t);u.push(o),o=a.__iterator(n,i)}else o=u.pop()}return{value:void 0,done:!0}}))},n}function Pt(t,e,r){e||(e=Ft);var n=w(t),i=0,o=t.toSeq().map((function(e,n){return[n,e,i++,r?r(e,n,t):e]})).valueSeq().toArray();return o.sort((function(t,r){return e(t[3],r[3])||t[2]-r[2]})).forEach(n?function(t,e){o[e].length=2}:function(t,e){o[e]=t[1]}),n?F(o):z(t)?G(o):Z(o)}function Wt(t,e,r){if(e||(e=Ft),r){var n=t.toSeq().map((function(e,n){return[e,r(e,n,t)]})).reduce((function(t,r){return Nt(e,t[1],r[1])?r:t}));return n&&n[0]}return t.reduce((function(t,r){return Nt(e,t,r)?r:t}))}function Nt(t,e,r){var n=t(r,e);return 0===n&&r!==e&&(null==r||r!=r)||n>0}function Ht(t,e,r,n){var i=Qt(t),o=new $(r).map((function(t){return t.size}));return i.size=n?o.max():o.min(),i.__iterate=function(t,e){for(var r,n=this.__iterator(U,e),i=0;!(r=n.next()).done&&!1!==t(r.value,i++,this););return i},i.__iteratorUncached=function(t,i){var o=r.map((function(t){return t=b(t),J(i?t.reverse():t)})),u=0,s=!1;return new C((function(){var r;return s||(r=o.map((function(t){return t.next()})),s=n?r.every((function(t){return t.done})):r.some((function(t){return t.done}))),s?{value:void 0,done:!0}:P(t,u++,e.apply(null,r.map((function(t){return t.value}))))}))},i}function Jt(t,e){return t===e?t:j(t)?e:t.constructor(e)}function Vt(t){if(t!==Object(t))throw new TypeError("Expected [K, V] tuple: "+t)}function Yt(t){return w(t)?I:z(t)?O:E}function Qt(t){return Object.create((w(t)?F:z(t)?G:Z).prototype)}function Xt(){return this._iter.cacheResult?(this._iter.cacheResult(),this.size=this._iter.size,this):X.prototype.cacheResult.call(this)}function Ft(t,e){return void 0===t&&void 0===e?0:void 0===t?1:void 0===e?-1:t>e?1:t<e?-1:0}function Gt(t,e){e=e||0;for(var r=Math.max(0,t.length-e),n=new Array(r),i=0;i<r;i++)n[i]=t[i+e];return n}function Zt(t,e){if(!t)throw new Error(e)}function $t(t){Zt(t!==1/0,"Cannot perform this action with an infinite size.")}function te(t){if(Q(t)&&"string"!=typeof t)return t;if(k(t))return t.toArray();throw new TypeError("Invalid keyPath: expected Ordered Collection or Array: "+t)}xt.prototype.cacheResult=Dt.prototype.cacheResult=At.prototype.cacheResult=kt.prototype.cacheResult=Xt;var ee=Object.prototype.toString;function re(t){if(!t||"object"!=typeof t||"[object Object]"!==ee.call(t))return!1;var e=Object.getPrototypeOf(t);if(null===e)return!0;for(var r=e,n=Object.getPrototypeOf(e);null!==n;)r=n,n=Object.getPrototypeOf(r);return r===e}function ne(t){return"object"==typeof t&&(x(t)||Array.isArray(t)||re(t))}function ie(t){try{return"string"==typeof t?JSON.stringify(t):String(t)}catch(e){return JSON.stringify(t)}}function oe(t,e){return x(t)?t.has(e):ne(t)&&Y.call(t,e)}function ue(t,e,r){return x(t)?t.get(e,r):oe(t,e)?"function"==typeof t.get?t.get(e):t[e]:r}function se(t){if(Array.isArray(t))return Gt(t);var e={};for(var r in t)Y.call(t,r)&&(e[r]=t[r]);return e}function ae(t,e){if(!ne(t))throw new TypeError("Cannot update non-data-structure value: "+t);if(x(t)){if(!t.remove)throw new TypeError("Cannot update immutable value without .remove() method: "+t);return t.remove(e)}if(!Y.call(t,e))return t;var r=se(t);return Array.isArray(r)?r.splice(e,1):delete r[e],r}function ce(t,e,r){if(!ne(t))throw new TypeError("Cannot update non-data-structure value: "+t);if(x(t)){if(!t.set)throw new TypeError("Cannot update immutable value without .set() method: "+t);return t.set(e,r)}if(Y.call(t,e)&&r===t[e])return t;var n=se(t);return n[e]=r,n}function fe(t,e,r,n){n||(n=r,r=void 0);var i=he(x(t),t,te(e),0,r,n);return i===o?r:i}function he(t,e,r,n,i,u){var s=e===o;if(n===r.length){var a=s?i:e,c=u(a);return c===a?e:c}if(!s&&!ne(e))throw new TypeError("Cannot update within non-data-structure value in path ["+r.slice(0,n).map(ie)+"]: "+e);var f=r[n],h=s?o:ue(e,f,o),p=he(h===o?t:x(h),h,r,n+1,i,u);return p===h?e:p===o?ae(e,f):ce(s?t?He():{}:e,f,p)}function pe(t,e,r){return fe(t,e,o,(function(){return r}))}function _e(t,e){return pe(this,t,e)}function le(t,e){return fe(t,e,(function(){return o}))}function ve(t){return le(this,t)}function ye(t,e,r,n){return fe(t,[e],r,n)}function de(t,e,r){return 1===arguments.length?t(this):ye(this,t,e,r)}function ge(t,e,r){return fe(this,t,e,r)}function we(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return ze(this,t)}function me(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];if("function"!=typeof t)throw new TypeError("Invalid merger function: "+t);return ze(this,e,t)}function ze(t,e,r){for(var n=[],i=0;i<e.length;i++){var u=I(e[i]);0!==u.size&&n.push(u)}return 0===n.length?t:0!==t.toSeq().size||t.__ownerID||1!==n.length?t.withMutations((function(t){for(var e=r?function(e,n){ye(t,n,o,(function(t){return t===o?e:r(t,e,n)}))}:function(e,r){t.set(r,e)},i=0;i<n.length;i++)n[i].forEach(e)})):t.constructor(n[0])}function Se(t,e,r){return be(t,e,function(t){function e(r,n,i){return ne(r)&&ne(n)&&(o=n,u=X(r),s=X(o),z(u)===z(s)&&w(u)===w(s))?be(r,[n],e):t?t(r,n,i):n;var o,u,s}return e}(r))}function be(t,e,r){if(!ne(t))throw new TypeError("Cannot merge into non-data-structure value: "+t);if(x(t))return"function"==typeof r&&t.mergeWith?t.mergeWith.apply(t,[r].concat(e)):t.merge?t.merge.apply(t,e):t.concat.apply(t,e);for(var n=Array.isArray(t),i=t,o=n?O:I,u=n?function(e){i===t&&(i=se(i)),i.push(e)}:function(e,n){var o=Y.call(i,n),u=o&&r?r(i[n],e,n):e;o&&u===i[n]||(i===t&&(i=se(i)),i[n]=u)},s=0;s<e.length;s++)o(e[s]).forEach(u);return i}function Ie(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return Se(this,t)}function Oe(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return Se(this,e,t)}function Ee(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return fe(this,t,He(),(function(t){return be(t,e)}))}function qe(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return fe(this,t,He(),(function(t){return Se(t,e)}))}function je(t){var e=this.asMutable();return t(e),e.wasAltered()?e.__ensureOwner(this.__ownerID):this}function Me(){return this.__ownerID?this:this.__ensureOwner(new s)}function De(){return this.__ensureOwner()}function xe(){return this.__altered}var Ae=function(t){function e(e){return null==e?He():at(e)&&!k(e)?e:He().withMutations((function(r){var n=t(e);$t(n.size),n.forEach((function(t,e){return r.set(e,t)}))}))}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.toString=function(){return this.__toString("Map {","}")},e.prototype.get=function(t,e){return this._root?this._root.get(0,void 0,t,e):e},e.prototype.set=function(t,e){return Je(this,t,e)},e.prototype.remove=function(t){return Je(this,t,o)},e.prototype.deleteAll=function(t){var e=b(t);return 0===e.size?this:this.withMutations((function(t){e.forEach((function(e){return t.remove(e)}))}))},e.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._root=null,this.__hash=void 0,this.__altered=!0,this):He()},e.prototype.sort=function(t){return vr(Pt(this,t))},e.prototype.sortBy=function(t,e){return vr(Pt(this,e,t))},e.prototype.map=function(t,e){var r=this;return this.withMutations((function(n){n.forEach((function(i,o){n.set(o,t.call(e,i,o,r))}))}))},e.prototype.__iterator=function(t,e){return new Ce(this,t,e)},e.prototype.__iterate=function(t,e){var r=this,n=0;return this._root&&this._root.iterate((function(e){return n++,t(e[1],e[0],r)}),e),n},e.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?Ne(this.size,this._root,t,this.__hash):0===this.size?He():(this.__ownerID=t,this.__altered=!1,this)},e}(I);Ae.isMap=at;var ke=Ae.prototype;ke[st]=!0,ke[e]=ke.remove,ke.removeAll=ke.deleteAll,ke.setIn=_e,ke.removeIn=ke.deleteIn=ve,ke.update=de,ke.updateIn=ge,ke.merge=ke.concat=we,ke.mergeWith=me,ke.mergeDeep=Ie,ke.mergeDeepWith=Oe,ke.mergeIn=Ee,ke.mergeDeepIn=qe,ke.withMutations=je,ke.wasAltered=xe,ke.asImmutable=De,ke["@@transducer/init"]=ke.asMutable=Me,ke["@@transducer/step"]=function(t,e){return t.set(e[0],e[1])},ke["@@transducer/result"]=function(t){return t.asImmutable()};var Re=function(t,e){this.ownerID=t,this.entries=e};Re.prototype.get=function(t,e,r,n){for(var i=this.entries,o=0,u=i.length;o<u;o++)if(ht(r,i[o][0]))return i[o][1];return n},Re.prototype.update=function(t,e,r,n,i,a,c){for(var f=i===o,h=this.entries,p=0,_=h.length;p<_&&!ht(n,h[p][0]);p++);var l=p<_;if(l?h[p][1]===i:f)return this;if(u(c),(f||!l)&&u(a),!f||1!==h.length){if(!l&&!f&&h.length>=Ge)return function(t,e,r,n){t||(t=new s);for(var i=new Ke(t,vt(r),[r,n]),o=0;o<e.length;o++){var u=e[o];i=i.update(t,0,void 0,u[0],u[1])}return i}(t,h,n,i);var v=t&&t===this.ownerID,y=v?h:Gt(h);return l?f?p===_-1?y.pop():y[p]=y.pop():y[p]=[n,i]:y.push([n,i]),v?(this.entries=y,this):new Re(t,y)}};var Ue=function(t,e,r){this.ownerID=t,this.bitmap=e,this.nodes=r};Ue.prototype.get=function(t,e,n,o){void 0===e&&(e=vt(n));var u=1<<((0===t?e:e>>>t)&i),s=this.bitmap;return 0==(s&u)?o:this.nodes[Xe(s&u-1)].get(t+r,e,n,o)},Ue.prototype.update=function(t,e,u,s,a,c,f){void 0===u&&(u=vt(s));var h=(0===e?u:u>>>e)&i,p=1<<h,_=this.bitmap,l=0!=(_&p);if(!l&&a===o)return this;var v=Xe(_&p-1),y=this.nodes,d=l?y[v]:void 0,g=Ve(d,t,e+r,u,s,a,c,f);if(g===d)return this;if(!l&&g&&y.length>=Ze)return function(t,e,r,i,o){for(var u=0,s=new Array(n),a=0;0!==r;a++,r>>>=1)s[a]=1&r?e[u++]:void 0;return s[i]=o,new Te(t,u+1,s)}(t,y,_,h,g);if(l&&!g&&2===y.length&&Ye(y[1^v]))return y[1^v];if(l&&g&&1===y.length&&Ye(g))return g;var w=t&&t===this.ownerID,m=l?g?_:_^p:_|p,z=l?g?Fe(y,v,g,w):function(t,e,r){var n=t.length-1;if(r&&e===n)return t.pop(),t;for(var i=new Array(n),o=0,u=0;u<n;u++)u===e&&(o=1),i[u]=t[u+o];return i}(y,v,w):function(t,e,r,n){var i=t.length+1;if(n&&e+1===i)return t[e]=r,t;for(var o=new Array(i),u=0,s=0;s<i;s++)s===e?(o[s]=r,u=-1):o[s]=t[s+u];return o}(y,v,g,w);return w?(this.bitmap=m,this.nodes=z,this):new Ue(t,m,z)};var Te=function(t,e,r){this.ownerID=t,this.count=e,this.nodes=r};Te.prototype.get=function(t,e,n,o){void 0===e&&(e=vt(n));var u=(0===t?e:e>>>t)&i,s=this.nodes[u];return s?s.get(t+r,e,n,o):o},Te.prototype.update=function(t,e,n,u,s,a,c){void 0===n&&(n=vt(u));var f=(0===e?n:n>>>e)&i,h=s===o,p=this.nodes,_=p[f];if(h&&!_)return this;var l=Ve(_,t,e+r,n,u,s,a,c);if(l===_)return this;var v=this.count;if(_){if(!l&&--v<$e)return function(t,e,r,n){for(var i=0,o=0,u=new Array(r),s=0,a=1,c=e.length;s<c;s++,a<<=1){var f=e[s];void 0!==f&&s!==n&&(i|=a,u[o++]=f)}return new Ue(t,i,u)}(t,p,v,f)}else v++;var y=t&&t===this.ownerID,d=Fe(p,f,l,y);return y?(this.count=v,this.nodes=d,this):new Te(t,v,d)};var Be=function(t,e,r){this.ownerID=t,this.keyHash=e,this.entries=r};Be.prototype.get=function(t,e,r,n){for(var i=this.entries,o=0,u=i.length;o<u;o++)if(ht(r,i[o][0]))return i[o][1];return n},Be.prototype.update=function(t,e,r,n,i,s,a){void 0===r&&(r=vt(n));var c=i===o;if(r!==this.keyHash)return c?this:(u(a),u(s),Qe(this,t,e,r,[n,i]));for(var f=this.entries,h=0,p=f.length;h<p&&!ht(n,f[h][0]);h++);var _=h<p;if(_?f[h][1]===i:c)return this;if(u(a),(c||!_)&&u(s),c&&2===p)return new Ke(t,this.keyHash,f[1^h]);var l=t&&t===this.ownerID,v=l?f:Gt(f);return _?c?h===p-1?v.pop():v[h]=v.pop():v[h]=[n,i]:v.push([n,i]),l?(this.entries=v,this):new Be(t,this.keyHash,v)};var Ke=function(t,e,r){this.ownerID=t,this.keyHash=e,this.entry=r};Ke.prototype.get=function(t,e,r,n){return ht(r,this.entry[0])?this.entry[1]:n},Ke.prototype.update=function(t,e,r,n,i,s,a){var c=i===o,f=ht(n,this.entry[0]);return(f?i===this.entry[1]:c)?this:(u(a),c?void u(s):f?t&&t===this.ownerID?(this.entry[1]=i,this):new Ke(t,this.keyHash,[n,i]):(u(s),Qe(this,t,e,vt(n),[n,i])))},Re.prototype.iterate=Be.prototype.iterate=function(t,e){for(var r=this.entries,n=0,i=r.length-1;n<=i;n++)if(!1===t(r[e?i-n:n]))return!1},Ue.prototype.iterate=Te.prototype.iterate=function(t,e){for(var r=this.nodes,n=0,i=r.length-1;n<=i;n++){var o=r[e?i-n:n];if(o&&!1===o.iterate(t,e))return!1}},Ke.prototype.iterate=function(t,e){return t(this.entry)};var Le,Ce=function(t){function e(t,e,r){this._type=e,this._reverse=r,this._stack=t._root&&We(t._root)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.next=function(){for(var t=this._type,e=this._stack;e;){var r=e.node,n=e.index++,i=void 0;if(r.entry){if(0===n)return Pe(t,r.entry)}else if(r.entries){if(n<=(i=r.entries.length-1))return Pe(t,r.entries[this._reverse?i-n:n])}else if(n<=(i=r.nodes.length-1)){var o=r.nodes[this._reverse?i-n:n];if(o){if(o.entry)return Pe(t,o.entry);e=this._stack=We(o,e)}continue}e=this._stack=this._stack.__prev}return{value:void 0,done:!0}},e}(C);function Pe(t,e){return P(t,e[0],e[1])}function We(t,e){return{node:t,index:0,__prev:e}}function Ne(t,e,r,n){var i=Object.create(ke);return i.size=t,i._root=e,i.__ownerID=r,i.__hash=n,i.__altered=!1,i}function He(){return Le||(Le=Ne(0))}function Je(t,e,r){var n,i;if(t._root){var u={value:!1},s={value:!1};if(n=Ve(t._root,t.__ownerID,0,void 0,e,r,u,s),!s.value)return t;i=t.size+(u.value?r===o?-1:1:0)}else{if(r===o)return t;i=1,n=new Re(t.__ownerID,[[e,r]])}return t.__ownerID?(t.size=i,t._root=n,t.__hash=void 0,t.__altered=!0,t):n?Ne(i,n):He()}function Ve(t,e,r,n,i,s,a,c){return t?t.update(e,r,n,i,s,a,c):s===o?t:(u(c),u(a),new Ke(e,n,[i,s]))}function Ye(t){return t.constructor===Ke||t.constructor===Be}function Qe(t,e,n,o,u){if(t.keyHash===o)return new Be(e,o,[t.entry,u]);var s,a=(0===n?t.keyHash:t.keyHash>>>n)&i,c=(0===n?o:o>>>n)&i,f=a===c?[Qe(t,e,n+r,o,u)]:(s=new Ke(e,o,u),a<c?[t,s]:[s,t]);return new Ue(e,1<<a|1<<c,f)}function Xe(t){return t=(t=(858993459&(t-=t>>1&1431655765))+(t>>2&858993459))+(t>>4)&252645135,t+=t>>8,127&(t+=t>>16)}function Fe(t,e,r,n){var i=n?t:Gt(t);return i[e]=r,i}var Ge=n/4,Ze=n/2,$e=n/4,tr="@@__IMMUTABLE_LIST__@@";function er(t){return Boolean(t&&t[tr])}var rr=function(t){function e(e){var i=ar();if(null==e)return i;if(er(e))return e;var o=t(e),u=o.size;return 0===u?i:($t(u),u>0&&u<n?sr(0,u,r,null,new ir(o.toArray())):i.withMutations((function(t){t.setSize(u),o.forEach((function(e,r){return t.set(r,e)}))})))}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.of=function(){return this(arguments)},e.prototype.toString=function(){return this.__toString("List [","]")},e.prototype.get=function(t,e){if((t=c(this,t))>=0&&t<this.size){var r=hr(this,t+=this._origin);return r&&r.array[t&i]}return e},e.prototype.set=function(t,e){return function(t,e,r){if(e=c(t,e),e!=e)return t;if(e>=t.size||e<0)return t.withMutations((function(t){e<0?pr(t,e).set(0,r):pr(t,0,e+1).set(e,r)}));e+=t._origin;var n=t._tail,i=t._root,o={value:!1};e>=_r(t._capacity)?n=cr(n,t.__ownerID,0,e,r,o):i=cr(i,t.__ownerID,t._level,e,r,o);if(!o.value)return t;if(t.__ownerID)return t._root=i,t._tail=n,t.__hash=void 0,t.__altered=!0,t;return sr(t._origin,t._capacity,t._level,i,n)}(this,t,e)},e.prototype.remove=function(t){return this.has(t)?0===t?this.shift():t===this.size-1?this.pop():this.splice(t,1):this},e.prototype.insert=function(t,e){return this.splice(t,0,e)},e.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=this._origin=this._capacity=0,this._level=r,this._root=this._tail=this.__hash=void 0,this.__altered=!0,this):ar()},e.prototype.push=function(){var t=arguments,e=this.size;return this.withMutations((function(r){pr(r,0,e+t.length);for(var n=0;n<t.length;n++)r.set(e+n,t[n])}))},e.prototype.pop=function(){return pr(this,0,-1)},e.prototype.unshift=function(){var t=arguments;return this.withMutations((function(e){pr(e,-t.length);for(var r=0;r<t.length;r++)e.set(r,t[r])}))},e.prototype.shift=function(){return pr(this,1)},e.prototype.concat=function(){for(var e=arguments,r=[],n=0;n<arguments.length;n++){var i=e[n],o=t("string"!=typeof i&&N(i)?i:[i]);0!==o.size&&r.push(o)}return 0===r.length?this:0!==this.size||this.__ownerID||1!==r.length?this.withMutations((function(t){r.forEach((function(e){return e.forEach((function(e){return t.push(e)}))}))})):this.constructor(r[0])},e.prototype.setSize=function(t){return pr(this,0,t)},e.prototype.map=function(t,e){var r=this;return this.withMutations((function(n){for(var i=0;i<r.size;i++)n.set(i,t.call(e,n.get(i),i,r))}))},e.prototype.slice=function(t,e){var r=this.size;return h(t,e,r)?this:pr(this,p(t,r),_(e,r))},e.prototype.__iterator=function(t,e){var r=e?this.size:0,n=ur(this,e);return new C((function(){var i=n();return i===or?{value:void 0,done:!0}:P(t,e?--r:r++,i)}))},e.prototype.__iterate=function(t,e){for(var r,n=e?this.size:0,i=ur(this,e);(r=i())!==or&&!1!==t(r,e?--n:n++,this););return n},e.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?sr(this._origin,this._capacity,this._level,this._root,this._tail,t,this.__hash):0===this.size?ar():(this.__ownerID=t,this.__altered=!1,this)},e}(O);rr.isList=er;var nr=rr.prototype;nr[tr]=!0,nr[e]=nr.remove,nr.merge=nr.concat,nr.setIn=_e,nr.deleteIn=nr.removeIn=ve,nr.update=de,nr.updateIn=ge,nr.mergeIn=Ee,nr.mergeDeepIn=qe,nr.withMutations=je,nr.wasAltered=xe,nr.asImmutable=De,nr["@@transducer/init"]=nr.asMutable=Me,nr["@@transducer/step"]=function(t,e){return t.push(e)},nr["@@transducer/result"]=function(t){return t.asImmutable()};var ir=function(t,e){this.array=t,this.ownerID=e};ir.prototype.removeBefore=function(t,e,n){if(0==(n&(1<<e+r)-1)||0===this.array.length)return this;var o=n>>>e&i;if(o>=this.array.length)return new ir([],t);var u,s=0===o;if(e>0){var a=this.array[o];if((u=a&&a.removeBefore(t,e-r,n))===a&&s)return this}if(s&&!u)return this;var c=fr(this,t);if(!s)for(var f=0;f<o;f++)c.array[f]=void 0;return u&&(c.array[o]=u),c},ir.prototype.removeAfter=function(t,e,o){if(o===(e?1<<e+r:n)||0===this.array.length)return this;var u,s=o-1>>>e&i;if(s>=this.array.length)return this;if(e>0){var a=this.array[s];if((u=a&&a.removeAfter(t,e-r,o))===a&&s===this.array.length-1)return this}var c=fr(this,t);return c.array.splice(s+1),u&&(c.array[s]=u),c};var or={};function ur(t,e){var i=t._origin,o=t._capacity,u=_r(o),s=t._tail;return a(t._root,t._level,0);function a(t,c,f){return 0===c?function(t,r){var a=r===u?s&&s.array:t&&t.array,c=r>i?0:i-r,f=o-r;f>n&&(f=n);return function(){if(c===f)return or;var t=e?--f:c++;return a&&a[t]}}(t,f):function(t,u,s){var c,f=t&&t.array,h=s>i?0:i-s>>u,p=1+(o-s>>u);p>n&&(p=n);return function(){for(;;){if(c){var t=c();if(t!==or)return t;c=null}if(h===p)return or;var n=e?--p:h++;c=a(f&&f[n],u-r,s+(n<<u))}}}(t,c,f)}}function sr(t,e,r,n,i,o,u){var s=Object.create(nr);return s.size=e-t,s._origin=t,s._capacity=e,s._level=r,s._root=n,s._tail=i,s.__ownerID=o,s.__hash=u,s.__altered=!1,s}function ar(){return sr(0,0,r)}function cr(t,e,n,o,s,a){var c,f=o>>>n&i,h=t&&f<t.array.length;if(!h&&void 0===s)return t;if(n>0){var p=t&&t.array[f],_=cr(p,e,n-r,o,s,a);return _===p?t:((c=fr(t,e)).array[f]=_,c)}return h&&t.array[f]===s?t:(a&&u(a),c=fr(t,e),void 0===s&&f===c.array.length-1?c.array.pop():c.array[f]=s,c)}function fr(t,e){return e&&t&&e===t.ownerID?t:new ir(t?t.array.slice():[],e)}function hr(t,e){if(e>=_r(t._capacity))return t._tail;if(e<1<<t._level+r){for(var n=t._root,o=t._level;n&&o>0;)n=n.array[e>>>o&i],o-=r;return n}}function pr(t,e,n){void 0!==e&&(e|=0),void 0!==n&&(n|=0);var o=t.__ownerID||new s,u=t._origin,a=t._capacity,c=u+e,f=void 0===n?a:n<0?a+n:u+n;if(c===u&&f===a)return t;if(c>=f)return t.clear();for(var h=t._level,p=t._root,_=0;c+_<0;)p=new ir(p&&p.array.length?[void 0,p]:[],o),_+=1<<(h+=r);_&&(c+=_,u+=_,f+=_,a+=_);for(var l=_r(a),v=_r(f);v>=1<<h+r;)p=new ir(p&&p.array.length?[p]:[],o),h+=r;var y=t._tail,d=v<l?hr(t,f-1):v>l?new ir([],o):y;if(y&&v>l&&c<a&&y.array.length){for(var g=p=fr(p,o),w=h;w>r;w-=r){var m=l>>>w&i;g=g.array[m]=fr(g.array[m],o)}g.array[l>>>r&i]=y}if(f<a&&(d=d&&d.removeAfter(o,0,f)),c>=v)c-=v,f-=v,h=r,p=null,d=d&&d.removeBefore(o,0,c);else if(c>u||v<l){for(_=0;p;){var z=c>>>h&i;if(z!==v>>>h&i)break;z&&(_+=(1<<h)*z),h-=r,p=p.array[z]}p&&c>u&&(p=p.removeBefore(o,h,c-_)),p&&v<l&&(p=p.removeAfter(o,h,v-_)),_&&(c-=_,f-=_)}return t.__ownerID?(t.size=f-c,t._origin=c,t._capacity=f,t._level=h,t._root=p,t._tail=d,t.__hash=void 0,t.__altered=!0,t):sr(c,f,h,p,d)}function _r(t){return t<n?0:t-1>>>r<<r}var lr,vr=function(t){function e(t){return null==t?dr():ct(t)?t:dr().withMutations((function(e){var r=I(t);$t(r.size),r.forEach((function(t,r){return e.set(r,t)}))}))}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.of=function(){return this(arguments)},e.prototype.toString=function(){return this.__toString("OrderedMap {","}")},e.prototype.get=function(t,e){var r=this._map.get(t);return void 0!==r?this._list.get(r)[1]:e},e.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._map.clear(),this._list.clear(),this.__altered=!0,this):dr()},e.prototype.set=function(t,e){return gr(this,t,e)},e.prototype.remove=function(t){return gr(this,t,o)},e.prototype.__iterate=function(t,e){var r=this;return this._list.__iterate((function(e){return e&&t(e[1],e[0],r)}),e)},e.prototype.__iterator=function(t,e){return this._list.fromEntrySeq().__iterator(t,e)},e.prototype.__ensureOwner=function(t){if(t===this.__ownerID)return this;var e=this._map.__ensureOwner(t),r=this._list.__ensureOwner(t);return t?yr(e,r,t,this.__hash):0===this.size?dr():(this.__ownerID=t,this.__altered=!1,this._map=e,this._list=r,this)},e}(Ae);function yr(t,e,r,n){var i=Object.create(vr.prototype);return i.size=t?t.size:0,i._map=t,i._list=e,i.__ownerID=r,i.__hash=n,i.__altered=!1,i}function dr(){return lr||(lr=yr(He(),ar()))}function gr(t,e,r){var i,u,s=t._map,a=t._list,c=s.get(e),f=void 0!==c;if(r===o){if(!f)return t;a.size>=n&&a.size>=2*s.size?(i=(u=a.filter((function(t,e){return void 0!==t&&c!==e}))).toKeyedSeq().map((function(t){return t[0]})).flip().toMap(),t.__ownerID&&(i.__ownerID=u.__ownerID=t.__ownerID)):(i=s.remove(e),u=c===a.size-1?a.pop():a.set(c,void 0))}else if(f){if(r===a.get(c)[1])return t;i=s,u=a.set(c,[e,r])}else i=s.set(e,a.size),u=a.set(a.size,[e,r]);return t.__ownerID?(t.size=i.size,t._map=i,t._list=u,t.__hash=void 0,t.__altered=!0,t):yr(i,u)}vr.isOrderedMap=ct,vr.prototype[A]=!0,vr.prototype[e]=vr.prototype.remove;var wr="@@__IMMUTABLE_STACK__@@";function mr(t){return Boolean(t&&t[wr])}var zr=function(t){function e(t){return null==t?Or():mr(t)?t:Or().pushAll(t)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.of=function(){return this(arguments)},e.prototype.toString=function(){return this.__toString("Stack [","]")},e.prototype.get=function(t,e){var r=this._head;for(t=c(this,t);r&&t--;)r=r.next;return r?r.value:e},e.prototype.peek=function(){return this._head&&this._head.value},e.prototype.push=function(){var t=arguments;if(0===arguments.length)return this;for(var e=this.size+arguments.length,r=this._head,n=arguments.length-1;n>=0;n--)r={value:t[n],next:r};return this.__ownerID?(this.size=e,this._head=r,this.__hash=void 0,this.__altered=!0,this):Ir(e,r)},e.prototype.pushAll=function(e){if(0===(e=t(e)).size)return this;if(0===this.size&&mr(e))return e;$t(e.size);var r=this.size,n=this._head;return e.__iterate((function(t){r++,n={value:t,next:n}}),!0),this.__ownerID?(this.size=r,this._head=n,this.__hash=void 0,this.__altered=!0,this):Ir(r,n)},e.prototype.pop=function(){return this.slice(1)},e.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._head=void 0,this.__hash=void 0,this.__altered=!0,this):Or()},e.prototype.slice=function(e,r){if(h(e,r,this.size))return this;var n=p(e,this.size);if(_(r,this.size)!==this.size)return t.prototype.slice.call(this,e,r);for(var i=this.size-n,o=this._head;n--;)o=o.next;return this.__ownerID?(this.size=i,this._head=o,this.__hash=void 0,this.__altered=!0,this):Ir(i,o)},e.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?Ir(this.size,this._head,t,this.__hash):0===this.size?Or():(this.__ownerID=t,this.__altered=!1,this)},e.prototype.__iterate=function(t,e){var r=this;if(e)return new $(this.toArray()).__iterate((function(e,n){return t(e,n,r)}),e);for(var n=0,i=this._head;i&&!1!==t(i.value,n++,this);)i=i.next;return n},e.prototype.__iterator=function(t,e){if(e)return new $(this.toArray()).__iterator(t,e);var r=0,n=this._head;return new C((function(){if(n){var e=n.value;return n=n.next,P(t,r++,e)}return{value:void 0,done:!0}}))},e}(O);zr.isStack=mr;var Sr,br=zr.prototype;function Ir(t,e,r,n){var i=Object.create(br);return i.size=t,i._head=e,i.__ownerID=r,i.__hash=n,i.__altered=!1,i}function Or(){return Sr||(Sr=Ir(0))}br[wr]=!0,br.shift=br.pop,br.unshift=br.push,br.unshiftAll=br.pushAll,br.withMutations=je,br.wasAltered=xe,br.asImmutable=De,br["@@transducer/init"]=br.asMutable=Me,br["@@transducer/step"]=function(t,e){return t.unshift(e)},br["@@transducer/result"]=function(t){return t.asImmutable()};var Er="@@__IMMUTABLE_SET__@@";function qr(t){return Boolean(t&&t[Er])}function jr(t){return qr(t)&&k(t)}function Mr(t,e){if(t===e)return!0;if(!d(e)||void 0!==t.size&&void 0!==e.size&&t.size!==e.size||void 0!==t.__hash&&void 0!==e.__hash&&t.__hash!==e.__hash||w(t)!==w(e)||z(t)!==z(e)||k(t)!==k(e))return!1;if(0===t.size&&0===e.size)return!0;var r=!S(t);if(k(t)){var n=t.entries();return e.every((function(t,e){var i=n.next().value;return i&&ht(i[1],t)&&(r||ht(i[0],e))}))&&n.next().done}var i=!1;if(void 0===t.size)if(void 0===e.size)"function"==typeof t.cacheResult&&t.cacheResult();else{i=!0;var u=t;t=e,e=u}var s=!0,a=e.__iterate((function(e,n){if(r?!t.has(e):i?!ht(e,t.get(n,o)):!ht(t.get(n,o),e))return s=!1,!1}));return s&&t.size===a}function Dr(t,e){var r=function(r){t.prototype[r]=e[r]};return Object.keys(e).forEach(r),Object.getOwnPropertySymbols&&Object.getOwnPropertySymbols(e).forEach(r),t}function xr(t){if(!t||"object"!=typeof t)return t;if(!d(t)){if(!ne(t))return t;t=X(t)}if(w(t)){var e={};return t.__iterate((function(t,r){e[r]=xr(t)})),e}var r=[];return t.__iterate((function(t){r.push(xr(t))})),r}var Ar=function(t){function e(e){return null==e?Br():qr(e)&&!k(e)?e:Br().withMutations((function(r){var n=t(e);$t(n.size),n.forEach((function(t){return r.add(t)}))}))}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.of=function(){return this(arguments)},e.fromKeys=function(t){return this(I(t).keySeq())},e.intersect=function(t){return(t=b(t).toArray()).length?Rr.intersect.apply(e(t.pop()),t):Br()},e.union=function(t){return(t=b(t).toArray()).length?Rr.union.apply(e(t.pop()),t):Br()},e.prototype.toString=function(){return this.__toString("Set {","}")},e.prototype.has=function(t){return this._map.has(t)},e.prototype.add=function(t){return Ur(this,this._map.set(t,t))},e.prototype.remove=function(t){return Ur(this,this._map.remove(t))},e.prototype.clear=function(){return Ur(this,this._map.clear())},e.prototype.map=function(t,e){var r=this,n=!1,i=Ur(this,this._map.mapEntries((function(i){var o=i[1],u=t.call(e,o,o,r);return u!==o&&(n=!0),[u,u]}),e));return n?i:this},e.prototype.union=function(){for(var e=[],r=arguments.length;r--;)e[r]=arguments[r];return 0===(e=e.filter((function(t){return 0!==t.size}))).length?this:0!==this.size||this.__ownerID||1!==e.length?this.withMutations((function(r){for(var n=0;n<e.length;n++)"string"==typeof e[n]?r.add(e[n]):t(e[n]).forEach((function(t){return r.add(t)}))})):this.constructor(e[0])},e.prototype.intersect=function(){for(var e=[],r=arguments.length;r--;)e[r]=arguments[r];if(0===e.length)return this;e=e.map((function(e){return t(e)}));var n=[];return this.forEach((function(t){e.every((function(e){return e.includes(t)}))||n.push(t)})),this.withMutations((function(t){n.forEach((function(e){t.remove(e)}))}))},e.prototype.subtract=function(){for(var e=[],r=arguments.length;r--;)e[r]=arguments[r];if(0===e.length)return this;e=e.map((function(e){return t(e)}));var n=[];return this.forEach((function(t){e.some((function(e){return e.includes(t)}))&&n.push(t)})),this.withMutations((function(t){n.forEach((function(e){t.remove(e)}))}))},e.prototype.sort=function(t){return rn(Pt(this,t))},e.prototype.sortBy=function(t,e){return rn(Pt(this,e,t))},e.prototype.wasAltered=function(){return this._map.wasAltered()},e.prototype.__iterate=function(t,e){var r=this;return this._map.__iterate((function(e){return t(e,e,r)}),e)},e.prototype.__iterator=function(t,e){return this._map.__iterator(t,e)},e.prototype.__ensureOwner=function(t){if(t===this.__ownerID)return this;var e=this._map.__ensureOwner(t);return t?this.__make(e,t):0===this.size?this.__empty():(this.__ownerID=t,this._map=e,this)},e}(E);Ar.isSet=qr;var kr,Rr=Ar.prototype;function Ur(t,e){return t.__ownerID?(t.size=e.size,t._map=e,t):e===t._map?t:0===e.size?t.__empty():t.__make(e)}function Tr(t,e){var r=Object.create(Rr);return r.size=t?t.size:0,r._map=t,r.__ownerID=e,r}function Br(){return kr||(kr=Tr(He()))}Rr[Er]=!0,Rr[e]=Rr.remove,Rr.merge=Rr.concat=Rr.union,Rr.withMutations=je,Rr.asImmutable=De,Rr["@@transducer/init"]=Rr.asMutable=Me,Rr["@@transducer/step"]=function(t,e){return t.add(e)},Rr["@@transducer/result"]=function(t){return t.asImmutable()},Rr.__empty=Br,Rr.__make=Tr;var Kr,Lr=function(t){function e(t,r,n){if(void 0===n&&(n=1),!(this instanceof e))return new e(t,r,n);if(Zt(0!==n,"Cannot step a Range by 0"),Zt(void 0!==t,"You must define a start value when using Range"),Zt(void 0!==r,"You must define an end value when using Range"),n=Math.abs(n),r<t&&(n=-n),this._start=t,this._end=r,this._step=n,this.size=Math.max(0,Math.ceil((r-t)/n-1)+1),0===this.size){if(Kr)return Kr;Kr=this}}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.toString=function(){return 0===this.size?"Range []":"Range [ "+this._start+"..."+this._end+(1!==this._step?" by "+this._step:"")+" ]"},e.prototype.get=function(t,e){return this.has(t)?this._start+c(this,t)*this._step:e},e.prototype.includes=function(t){var e=(t-this._start)/this._step;return e>=0&&e<this.size&&e===Math.floor(e)},e.prototype.slice=function(t,r){return h(t,r,this.size)?this:(t=p(t,this.size),(r=_(r,this.size))<=t?new e(0,0):new e(this.get(t,this._end),this.get(r,this._end),this._step))},e.prototype.indexOf=function(t){var e=t-this._start;if(e%this._step==0){var r=e/this._step;if(r>=0&&r<this.size)return r}return-1},e.prototype.lastIndexOf=function(t){return this.indexOf(t)},e.prototype.__iterate=function(t,e){for(var r=this.size,n=this._step,i=e?this._start+(r-1)*n:this._start,o=0;o!==r&&!1!==t(i,e?r-++o:o++,this);)i+=e?-n:n;return o},e.prototype.__iterator=function(t,e){var r=this.size,n=this._step,i=e?this._start+(r-1)*n:this._start,o=0;return new C((function(){if(o===r)return{value:void 0,done:!0};var u=i;return i+=e?-n:n,P(t,e?r-++o:o++,u)}))},e.prototype.equals=function(t){return t instanceof e?this._start===t._start&&this._end===t._end&&this._step===t._step:Mr(this,t)},e}(G);function Cr(t,e,r){for(var n=te(e),i=0;i!==n.length;)if((t=ue(t,n[i++],o))===o)return r;return t}function Pr(t,e){return Cr(this,t,e)}function Wr(t,e){return Cr(t,e,o)!==o}function Nr(){$t(this.size);var t={};return this.__iterate((function(e,r){t[r]=e})),t}b.Iterator=C,Dr(b,{toArray:function(){$t(this.size);var t=new Array(this.size||0),e=w(this),r=0;return this.__iterate((function(n,i){t[r++]=e?[i,n]:n})),t},toIndexedSeq:function(){return new xt(this)},toJS:function(){return xr(this)},toKeyedSeq:function(){return new Dt(this,!0)},toMap:function(){return Ae(this.toKeyedSeq())},toObject:Nr,toOrderedMap:function(){return vr(this.toKeyedSeq())},toOrderedSet:function(){return rn(w(this)?this.valueSeq():this)},toSet:function(){return Ar(w(this)?this.valueSeq():this)},toSetSeq:function(){return new At(this)},toSeq:function(){return z(this)?this.toIndexedSeq():w(this)?this.toKeyedSeq():this.toSetSeq()},toStack:function(){return zr(w(this)?this.valueSeq():this)},toList:function(){return rr(w(this)?this.valueSeq():this)},toString:function(){return"[Collection]"},__toString:function(t,e){return 0===this.size?t+e:t+" "+this.toSeq().map(this.__toStringMapper).join(", ")+" "+e},concat:function(){for(var t=[],e=arguments.length;e--;)t[e]=arguments[e];return Jt(this,function(t,e){var r=w(t),n=[t].concat(e).map((function(t){return d(t)?r&&(t=I(t)):t=r?it(t):ot(Array.isArray(t)?t:[t]),t})).filter((function(t){return 0!==t.size}));if(0===n.length)return t;if(1===n.length){var i=n[0];if(i===t||r&&w(i)||z(t)&&z(i))return i}var o=new $(n);return r?o=o.toKeyedSeq():z(t)||(o=o.toSetSeq()),(o=o.flatten(!0)).size=n.reduce((function(t,e){if(void 0!==t){var r=e.size;if(void 0!==r)return t+r}}),0),o}(this,t))},includes:function(t){return this.some((function(e){return ht(e,t)}))},entries:function(){return this.__iterator(T)},every:function(t,e){$t(this.size);var r=!0;return this.__iterate((function(n,i,o){if(!t.call(e,n,i,o))return r=!1,!1})),r},filter:function(t,e){return Jt(this,Bt(this,t,e,!0))},partition:function(t,e){return function(t,e,r){var n=w(t),i=[[],[]];t.__iterate((function(o,u){i[e.call(r,o,u,t)?1:0].push(n?[u,o]:o)}));var o=Yt(t);return i.map((function(e){return Jt(t,o(e))}))}(this,t,e)},find:function(t,e,r){var n=this.findEntry(t,e);return n?n[1]:r},forEach:function(t,e){return $t(this.size),this.__iterate(e?t.bind(e):t)},join:function(t){$t(this.size),t=void 0!==t?""+t:",";var e="",r=!0;return this.__iterate((function(n){r?r=!1:e+=t,e+=null!=n?n.toString():""})),e},keys:function(){return this.__iterator(R)},map:function(t,e){return Jt(this,Ut(this,t,e))},reduce:function(t,e,r){return Qr(this,t,e,r,arguments.length<2,!1)},reduceRight:function(t,e,r){return Qr(this,t,e,r,arguments.length<2,!0)},reverse:function(){return Jt(this,Tt(this,!0))},slice:function(t,e){return Jt(this,Kt(this,t,e,!0))},some:function(t,e){$t(this.size);var r=!1;return this.__iterate((function(n,i,o){if(t.call(e,n,i,o))return r=!0,!1})),r},sort:function(t){return Jt(this,Pt(this,t))},values:function(){return this.__iterator(U)},butLast:function(){return this.slice(0,-1)},isEmpty:function(){return void 0!==this.size?0===this.size:!this.some((function(){return!0}))},count:function(t,e){return a(t?this.toSeq().filter(t,e):this)},countBy:function(t,e){return function(t,e,r){var n=Ae().asMutable();return t.__iterate((function(i,o){n.update(e.call(r,i,o,t),0,(function(t){return t+1}))})),n.asImmutable()}(this,t,e)},equals:function(t){return Mr(this,t)},entrySeq:function(){var t=this;if(t._cache)return new $(t._cache);var e=t.toSeq().map(Fr).toIndexedSeq();return e.fromEntrySeq=function(){return t.toSeq()},e},filterNot:function(t,e){return this.filter(Gr(t),e)},findEntry:function(t,e,r){var n=r;return this.__iterate((function(r,i,o){if(t.call(e,r,i,o))return n=[i,r],!1})),n},findKey:function(t,e){var r=this.findEntry(t,e);return r&&r[0]},findLast:function(t,e,r){return this.toKeyedSeq().reverse().find(t,e,r)},findLastEntry:function(t,e,r){return this.toKeyedSeq().reverse().findEntry(t,e,r)},findLastKey:function(t,e){return this.toKeyedSeq().reverse().findKey(t,e)},first:function(t){return this.find(f,null,t)},flatMap:function(t,e){return Jt(this,function(t,e,r){var n=Yt(t);return t.toSeq().map((function(i,o){return n(e.call(r,i,o,t))})).flatten(!0)}(this,t,e))},flatten:function(t){return Jt(this,Ct(this,t,!0))},fromEntrySeq:function(){return new kt(this)},get:function(t,e){return this.find((function(e,r){return ht(r,t)}),void 0,e)},getIn:Pr,groupBy:function(t,e){return function(t,e,r){var n=w(t),i=(k(t)?vr():Ae()).asMutable();t.__iterate((function(o,u){i.update(e.call(r,o,u,t),(function(t){return(t=t||[]).push(n?[u,o]:o),t}))}));var o=Yt(t);return i.map((function(e){return Jt(t,o(e))})).asImmutable()}(this,t,e)},has:function(t){return this.get(t,o)!==o},hasIn:function(t){return Wr(this,t)},isSubset:function(t){return t="function"==typeof t.includes?t:b(t),this.every((function(e){return t.includes(e)}))},isSuperset:function(t){return(t="function"==typeof t.isSubset?t:b(t)).isSubset(this)},keyOf:function(t){return this.findKey((function(e){return ht(e,t)}))},keySeq:function(){return this.toSeq().map(Xr).toIndexedSeq()},last:function(t){return this.toSeq().reverse().first(t)},lastKeyOf:function(t){return this.toKeyedSeq().reverse().keyOf(t)},max:function(t){return Wt(this,t)},maxBy:function(t,e){return Wt(this,e,t)},min:function(t){return Wt(this,t?Zr(t):tn)},minBy:function(t,e){return Wt(this,e?Zr(e):tn,t)},rest:function(){return this.slice(1)},skip:function(t){return 0===t?this:this.slice(Math.max(0,t))},skipLast:function(t){return 0===t?this:this.slice(0,-Math.max(0,t))},skipWhile:function(t,e){return Jt(this,Lt(this,t,e,!0))},skipUntil:function(t,e){return this.skipWhile(Gr(t),e)},sortBy:function(t,e){return Jt(this,Pt(this,e,t))},take:function(t){return this.slice(0,Math.max(0,t))},takeLast:function(t){return this.slice(-Math.max(0,t))},takeWhile:function(t,e){return Jt(this,function(t,e,r){var n=Qt(t);return n.__iterateUncached=function(n,i){var o=this;if(i)return this.cacheResult().__iterate(n,i);var u=0;return t.__iterate((function(t,i,s){return e.call(r,t,i,s)&&++u&&n(t,i,o)})),u},n.__iteratorUncached=function(n,i){var o=this;if(i)return this.cacheResult().__iterator(n,i);var u=t.__iterator(T,i),s=!0;return new C((function(){if(!s)return{value:void 0,done:!0};var t=u.next();if(t.done)return t;var i=t.value,a=i[0],c=i[1];return e.call(r,c,a,o)?n===T?t:P(n,a,c,t):(s=!1,{value:void 0,done:!0})}))},n}(this,t,e))},takeUntil:function(t,e){return this.takeWhile(Gr(t),e)},update:function(t){return t(this)},valueSeq:function(){return this.toIndexedSeq()},hashCode:function(){return this.__hash||(this.__hash=function(t){if(t.size===1/0)return 0;var e=k(t),r=w(t),n=e?1:0;return t.__iterate(r?e?function(t,e){n=31*n+en(vt(t),vt(e))|0}:function(t,e){n=n+en(vt(t),vt(e))|0}:e?function(t){n=31*n+vt(t)|0}:function(t){n=n+vt(t)|0}),function(t,e){return e=pt(e,3432918353),e=pt(e<<15|e>>>-15,461845907),e=pt(e<<13|e>>>-13,5),e=pt((e=(e+3864292196|0)^t)^e>>>16,2246822507),e=_t((e=pt(e^e>>>13,3266489909))^e>>>16)}(t.size,n)}(this))}});var Hr=b.prototype;Hr[y]=!0,Hr[L]=Hr.values,Hr.toJSON=Hr.toArray,Hr.__toStringMapper=ie,Hr.inspect=Hr.toSource=function(){return this.toString()},Hr.chain=Hr.flatMap,Hr.contains=Hr.includes,Dr(I,{flip:function(){return Jt(this,Rt(this))},mapEntries:function(t,e){var r=this,n=0;return Jt(this,this.toSeq().map((function(i,o){return t.call(e,[o,i],n++,r)})).fromEntrySeq())},mapKeys:function(t,e){var r=this;return Jt(this,this.toSeq().flip().map((function(n,i){return t.call(e,n,i,r)})).flip())}});var Jr=I.prototype;Jr[g]=!0,Jr[L]=Hr.entries,Jr.toJSON=Nr,Jr.__toStringMapper=function(t,e){return ie(e)+": "+ie(t)},Dr(O,{toKeyedSeq:function(){return new Dt(this,!1)},filter:function(t,e){return Jt(this,Bt(this,t,e,!1))},findIndex:function(t,e){var r=this.findEntry(t,e);return r?r[0]:-1},indexOf:function(t){var e=this.keyOf(t);return void 0===e?-1:e},lastIndexOf:function(t){var e=this.lastKeyOf(t);return void 0===e?-1:e},reverse:function(){return Jt(this,Tt(this,!1))},slice:function(t,e){return Jt(this,Kt(this,t,e,!1))},splice:function(t,e){var r=arguments.length;if(e=Math.max(e||0,0),0===r||2===r&&!e)return this;t=p(t,t<0?this.count():this.size);var n=this.slice(0,t);return Jt(this,1===r?n:n.concat(Gt(arguments,2),this.slice(t+e)))},findLastIndex:function(t,e){var r=this.findLastEntry(t,e);return r?r[0]:-1},first:function(t){return this.get(0,t)},flatten:function(t){return Jt(this,Ct(this,t,!1))},get:function(t,e){return(t=c(this,t))<0||this.size===1/0||void 0!==this.size&&t>this.size?e:this.find((function(e,r){return r===t}),void 0,e)},has:function(t){return(t=c(this,t))>=0&&(void 0!==this.size?this.size===1/0||t<this.size:-1!==this.indexOf(t))},interpose:function(t){return Jt(this,function(t,e){var r=Qt(t);return r.size=t.size&&2*t.size-1,r.__iterateUncached=function(r,n){var i=this,o=0;return t.__iterate((function(t){return(!o||!1!==r(e,o++,i))&&!1!==r(t,o++,i)}),n),o},r.__iteratorUncached=function(r,n){var i,o=t.__iterator(U,n),u=0;return new C((function(){return(!i||u%2)&&(i=o.next()).done?i:u%2?P(r,u++,e):P(r,u++,i.value,i)}))},r}(this,t))},interleave:function(){var t=[this].concat(Gt(arguments)),e=Ht(this.toSeq(),G.of,t),r=e.flatten(!0);return e.size&&(r.size=e.size*t.length),Jt(this,r)},keySeq:function(){return Lr(0,this.size)},last:function(t){return this.get(-1,t)},skipWhile:function(t,e){return Jt(this,Lt(this,t,e,!1))},zip:function(){return Jt(this,Ht(this,$r,[this].concat(Gt(arguments))))},zipAll:function(){return Jt(this,Ht(this,$r,[this].concat(Gt(arguments)),!0))},zipWith:function(t){var e=Gt(arguments);return e[0]=this,Jt(this,Ht(this,t,e))}});var Vr=O.prototype;Vr[m]=!0,Vr[A]=!0,Dr(E,{get:function(t,e){return this.has(t)?t:e},includes:function(t){return this.has(t)},keySeq:function(){return this.valueSeq()}});var Yr=E.prototype;function Qr(t,e,r,n,i,o){return $t(t.size),t.__iterate((function(t,o,u){i?(i=!1,r=t):r=e.call(n,r,t,o,u)}),o),r}function Xr(t,e){return e}function Fr(t,e){return[e,t]}function Gr(t){return function(){return!t.apply(this,arguments)}}function Zr(t){return function(){return-t.apply(this,arguments)}}function $r(){return Gt(arguments)}function tn(t,e){return t<e?1:t>e?-1:0}function en(t,e){return t^e+2654435769+(t<<6)+(t>>2)|0}Yr.has=Hr.includes,Yr.contains=Yr.includes,Yr.keys=Yr.values,Dr(F,Jr),Dr(G,Vr),Dr(Z,Yr);var rn=function(t){function e(t){return null==t?sn():jr(t)?t:sn().withMutations((function(e){var r=E(t);$t(r.size),r.forEach((function(t){return e.add(t)}))}))}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.of=function(){return this(arguments)},e.fromKeys=function(t){return this(I(t).keySeq())},e.prototype.toString=function(){return this.__toString("OrderedSet {","}")},e}(Ar);rn.isOrderedSet=jr;var nn,on=rn.prototype;function un(t,e){var r=Object.create(on);return r.size=t?t.size:0,r._map=t,r.__ownerID=e,r}function sn(){return nn||(nn=un(dr()))}on[A]=!0,on.zip=Vr.zip,on.zipWith=Vr.zipWith,on.zipAll=Vr.zipAll,on.__empty=sn,on.__make=un;var an=function(t,e){var r;!function(t){if(D(t))throw new Error("Can not call `Record` with an immutable Record as default values. Use a plain javascript object instead.");if(x(t))throw new Error("Can not call `Record` with an immutable Collection as default values. Use a plain javascript object instead.");if(null===t||"object"!=typeof t)throw new Error("Can not call `Record` with a non-object as default values. Use a plain javascript object instead.")}(t);var n=function(o){var u=this;if(o instanceof n)return o;if(!(this instanceof n))return new n(o);if(!r){r=!0;var s=Object.keys(t),a=i._indices={};i._name=e,i._keys=s,i._defaultValues=t;for(var c=0;c<s.length;c++){var f=s[c];a[f]=c,i[f]?"object"==typeof console&&console.warn&&console.warn("Cannot define "+hn(this)+' with property "'+f+'" since that property name is part of the Record API.'):_n(i,f)}}return this.__ownerID=void 0,this._values=rr().withMutations((function(t){t.setSize(u._keys.length),I(o).forEach((function(e,r){t.set(u._indices[r],e===u._defaultValues[r]?void 0:e)}))})),this},i=n.prototype=Object.create(cn);return i.constructor=n,e&&(n.displayName=e),n};an.prototype.toString=function(){for(var t,e=hn(this)+" { ",r=this._keys,n=0,i=r.length;n!==i;n++)e+=(n?", ":"")+(t=r[n])+": "+ie(this.get(t));return e+" }"},an.prototype.equals=function(t){return this===t||D(t)&&pn(this).equals(pn(t))},an.prototype.hashCode=function(){return pn(this).hashCode()},an.prototype.has=function(t){return this._indices.hasOwnProperty(t)},an.prototype.get=function(t,e){if(!this.has(t))return e;var r=this._indices[t],n=this._values.get(r);return void 0===n?this._defaultValues[t]:n},an.prototype.set=function(t,e){if(this.has(t)){var r=this._values.set(this._indices[t],e===this._defaultValues[t]?void 0:e);if(r!==this._values&&!this.__ownerID)return fn(this,r)}return this},an.prototype.remove=function(t){return this.set(t)},an.prototype.clear=function(){var t=this._values.clear().setSize(this._keys.length);return this.__ownerID?this:fn(this,t)},an.prototype.wasAltered=function(){return this._values.wasAltered()},an.prototype.toSeq=function(){return pn(this)},an.prototype.toJS=function(){return xr(this)},an.prototype.entries=function(){return this.__iterator(T)},an.prototype.__iterator=function(t,e){return pn(this).__iterator(t,e)},an.prototype.__iterate=function(t,e){return pn(this).__iterate(t,e)},an.prototype.__ensureOwner=function(t){if(t===this.__ownerID)return this;var e=this._values.__ensureOwner(t);return t?fn(this,e,t):(this.__ownerID=t,this._values=e,this)},an.isRecord=D,an.getDescriptiveName=hn;var cn=an.prototype;function fn(t,e,r){var n=Object.create(Object.getPrototypeOf(t));return n._values=e,n.__ownerID=r,n}function hn(t){return t.constructor.displayName||t.constructor.name||"Record"}function pn(t){return it(t._keys.map((function(e){return[e,t.get(e)]})))}function _n(t,e){try{Object.defineProperty(t,e,{get:function(){return this.get(e)},set:function(t){Zt(this.__ownerID,"Cannot set on an immutable record."),this.set(e,t)}})}catch(t){}}cn[M]=!0,cn[e]=cn.remove,cn.deleteIn=cn.removeIn=ve,cn.getIn=Pr,cn.hasIn=Hr.hasIn,cn.merge=we,cn.mergeWith=me,cn.mergeIn=Ee,cn.mergeDeep=Ie,cn.mergeDeepWith=Oe,cn.mergeDeepIn=qe,cn.setIn=_e,cn.update=de,cn.updateIn=ge,cn.withMutations=je,cn.asMutable=Me,cn.asImmutable=De,cn[L]=cn.entries,cn.toJSON=cn.toObject=Hr.toObject,cn.inspect=cn.toSource=function(){return this.toString()};var ln,vn=function(t){function e(t,r){if(!(this instanceof e))return new e(t,r);if(this._value=t,this.size=void 0===r?1/0:Math.max(0,r),0===this.size){if(ln)return ln;ln=this}}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.toString=function(){return 0===this.size?"Repeat []":"Repeat [ "+this._value+" "+this.size+" times ]"},e.prototype.get=function(t,e){return this.has(t)?this._value:e},e.prototype.includes=function(t){return ht(this._value,t)},e.prototype.slice=function(t,r){var n=this.size;return h(t,r,n)?this:new e(this._value,_(r,n)-p(t,n))},e.prototype.reverse=function(){return this},e.prototype.indexOf=function(t){return ht(this._value,t)?0:-1},e.prototype.lastIndexOf=function(t){return ht(this._value,t)?this.size:-1},e.prototype.__iterate=function(t,e){for(var r=this.size,n=0;n!==r&&!1!==t(this._value,e?r-++n:n++,this););return n},e.prototype.__iterator=function(t,e){var r=this,n=this.size,i=0;return new C((function(){return i===n?{value:void 0,done:!0}:P(t,e?n-++i:i++,r._value)}))},e.prototype.equals=function(t){return t instanceof e?ht(this._value,t._value):Mr(this,t)},e}(G);function yn(t,e,r,n,i,o){if("string"!=typeof r&&!x(r)&&(Q(r)||N(r)||re(r))){if(~t.indexOf(r))throw new TypeError("Cannot convert circular structure to Immutable");t.push(r),i&&""!==n&&i.push(n);var u=e.call(o,n,X(r).map((function(n,o){return yn(t,e,n,o,i,r)})),i&&i.slice());return t.pop(),i&&i.pop(),u}return r}function dn(t,e){return z(e)?e.toList():w(e)?e.toMap():e.toSet()}var gn=b;t.Collection=b,t.Iterable=gn,t.List=rr,t.Map=Ae,t.OrderedMap=vr,t.OrderedSet=rn,t.PairSorting={LeftThenRight:-1,RightThenLeft:1},t.Range=Lr,t.Record=an,t.Repeat=vn,t.Seq=X,t.Set=Ar,t.Stack=zr,t.fromJS=function(t,e){return yn([],e||dn,t,"",e&&e.length>2?[]:void 0,{"":t})},t.get=ue,t.getIn=Cr,t.has=oe,t.hasIn=Wr,t.hash=vt,t.is=ht,t.isAssociative=S,t.isCollection=d,t.isImmutable=x,t.isIndexed=z,t.isKeyed=w,t.isList=er,t.isMap=at,t.isOrdered=k,t.isOrderedMap=ct,t.isOrderedSet=jr,t.isPlainObject=re,t.isRecord=D,t.isSeq=j,t.isSet=qr,t.isStack=mr,t.isValueObject=ft,t.merge=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return be(t,e)},t.mergeDeep=function(t){for(var e=[],r=arguments.length-1;r-- >0;)e[r]=arguments[r+1];return Se(t,e)},t.mergeDeepWith=function(t,e){for(var r=[],n=arguments.length-2;n-- >0;)r[n]=arguments[n+2];return Se(e,r,t)},t.mergeWith=function(t,e){for(var r=[],n=arguments.length-2;n-- >0;)r[n]=arguments[n+2];return be(e,r,t)},t.remove=ae,t.removeIn=le,t.set=ce,t.setIn=pe,t.update=ye,t.updateIn=fe,t.version="5.0.3"}));
