text: /**
   * rubico v1.8.11
   * https://github.com/a-synchronous/rubico
   * (c) 2019-2021 Richard Tong
   * rubico may be freely distributed under the MIT license.
   */
  
  const isArray = Array.isArray
  
  const isPromise = value => value != null && typeof value.then == 'function'
  
  const __ = Symbol.for('placeholder')
  
  // argument resolver for curry3
  const curry3ResolveArg0 = (
    baseFunc, arg1, arg2,
  ) => function arg0Resolver(arg0) {
    return baseFunc(arg0, arg1, arg2)
  }
  
  // argument resolver for curry3
  const curry3ResolveArg1 = (
    baseFunc, arg0, arg2,
  ) => function arg1Resolver(arg1) {
    return baseFunc(arg0, arg1, arg2)
  }
  
  // argument resolver for curry3
  const curry3ResolveArg2 = (
    baseFunc, arg0, arg1,
  ) => function arg2Resolver(arg2) {
    return baseFunc(arg0, arg1, arg2)
  }
  
  const curry3 = function (baseFunc, arg0, arg1, arg2) {
    if (arg0 == __) {
      return curry3ResolveArg0(baseFunc, arg1, arg2)
    }
    if (arg1 == __) {
      return curry3ResolveArg1(baseFunc, arg0, arg2)
    }
    return curry3ResolveArg2(baseFunc, arg0, arg1)
  }
  
  // argument resolver for curryArgs3
  const curryArgs3ResolveArgs0 = (
    baseFunc, arg1, arg2,
  ) => function args0Resolver(...args) {
    return baseFunc(args, arg1, arg2)
  }
  
  // argument resolver for curryArgs3
  const curryArgs3ResolveArgs1 = (
    baseFunc, arg0, arg2,
  ) => function arg1Resolver(...args) {
    return baseFunc(arg0, args, arg2)
  }
  
  // argument resolver for curryArgs3
  const curryArgs3ResolveArgs2 = (
    baseFunc, arg0, arg1,
  ) => function arg2Resolver(...args) {
    return baseFunc(arg0, arg1, args)
  }
  
  const curryArgs3 = function (baseFunc, arg0, arg1, arg2) {
    if (arg0 == __) {
      return curryArgs3ResolveArgs0(baseFunc, arg1, arg2)
    }
    if (arg1 == __) {
      return curryArgs3ResolveArgs1(baseFunc, arg0, arg2)
    }
    return curryArgs3ResolveArgs2(baseFunc, arg0, arg1)
  }
  
  const objectValues = Object.values
  
  const objectProto = Object.prototype
  
  const nativeObjectToString = objectProto.toString
  
  const objectToString = value => nativeObjectToString.call(value)
  
  const generatorFunctionTag = '[object GeneratorFunction]'
  
  const isGeneratorFunction = value => objectToString(value) == generatorFunctionTag
  
  const asyncGeneratorFunctionTag = '[object AsyncGeneratorFunction]'
  
  const isAsyncGeneratorFunction = value => objectToString(value) == asyncGeneratorFunctionTag
  
  const iteratorReduceAsync = async function (
    iterator, reducer, result,
  ) {
    let iteration = iterator.next()
    if (iteration.done) {
      return result
    }
  
    while (!iteration.done) {
      result = reducer(result, iteration.value)
      if (isPromise(result)) {
        result = await result
      }
      iteration = iterator.next()
    }
    return result
  }
  
  const iteratorReduce = function (iterator, reducer, result) {
    let iteration = iterator.next()
    if (iteration.done) {
      return result
    }
    if (result === undefined) {
      result = iteration.value
      iteration = iterator.next()
    }
    while (!iteration.done) {
      result = reducer(result, iteration.value)
      if (isPromise(result)) {
        return result.then(curry3(iteratorReduceAsync, iterator, reducer, __))
      }
      iteration = iterator.next()
    }
    return result
  }
  
  const asyncIteratorReduce = async function (asyncIterator, reducer, result) {
    let iteration = await asyncIterator.next()
    if (iteration.done) {
      return result
    }
    if (result === undefined) {
      result = iteration.value
      iteration = await asyncIterator.next()
    }
  
    while (!iteration.done) {
      result = await reducer(result, iteration.value)
      iteration = await asyncIterator.next()
    }
    return result
  }
  
  const symbolIterator = Symbol.iterator
  
  const symbolAsyncIterator = Symbol.asyncIterator
  
  // argument resolver for curry2
  const curry2ResolveArg0 = (
    baseFunc, arg1,
  ) => function arg0Resolver(arg0) {
    return baseFunc(arg0, arg1)
  }
  
  // argument resolver for curry2
  const curry2ResolveArg1 = (
    baseFunc, arg0,
  ) => function arg1Resolver(arg1) {
    return baseFunc(arg0, arg1)
  }
  
  const curry2 = function (baseFunc, arg0, arg1) {
    return arg0 == __
      ? curry2ResolveArg0(baseFunc, arg1)
      : curry2ResolveArg1(baseFunc, arg0)
  }
  
  // argument resolver for curry4
  const curry4ResolveArg0 = (
    baseFunc, arg1, arg2, arg3,
  ) => function arg0Resolver(arg0) {
    return baseFunc(arg0, arg1, arg2, arg3)
  }
  
  // argument resolver for curry4
  const curry4ResolveArg1 = (
    baseFunc, arg0, arg2, arg3,
  ) => function arg1Resolver(arg1) {
    return baseFunc(arg0, arg1, arg2, arg3)
  }
  
  // argument resolver for curry4
  const curry4ResolveArg2 = (
    baseFunc, arg0, arg1, arg3,
  ) => function arg2Resolver(arg2) {
    return baseFunc(arg0, arg1, arg2, arg3)
  }
  
  // argument resolver for curry4
  const curry4ResolveArg3 = (
    baseFunc, arg0, arg1, arg2,
  ) => function arg3Resolver(arg3) {
    return baseFunc(arg0, arg1, arg2, arg3)
  }
  
  const curry4 = function (baseFunc, arg0, arg1, arg2, arg3) {
    if (arg0 == __) {
      return curry4ResolveArg0(baseFunc, arg1, arg2, arg3)
    }
    if (arg1 == __) {
      return curry4ResolveArg1(baseFunc, arg0, arg2, arg3)
    }
    if (arg2 == __) {
      return curry4ResolveArg2(baseFunc, arg0, arg1, arg3)
    }
    return curry4ResolveArg3(baseFunc, arg0, arg1, arg2)
  }
  
  const arrayReduceAsync = async function (
    array, reducer, result, index,
  ) {
    const length = array.length
    while (++index < length) {
      result = reducer(result, array[index], index, array)
      if (isPromise(result)) {
        result = await result
      }
    }
    return result
  }
  
  const arrayReduce = function (array, reducer, result) {
    const arrayLength = array.length
    let index = -1
    if (result === undefined) {
      result = array[++index]
    }
    while (++index < arrayLength) {
      result = reducer(result, array[index], index, array)
      if (isPromise(result)) {
        return result.then(curry4(arrayReduceAsync, array, reducer, __, index))
      }
    }
    return result
  }
  
  // argument resolver for curry5
  const curry5ResolveArg0 = (
    baseFunc, arg1, arg2, arg3, arg4,
  ) => function arg0Resolver(arg0) {
    return baseFunc(arg0, arg1, arg2, arg3, arg4)
  }
  
  // argument resolver for curry5
  const curry5ResolveArg1 = (
    baseFunc, arg0, arg2, arg3, arg4,
  ) => function arg1Resolver(arg1) {
    return baseFunc(arg0, arg1, arg2, arg3, arg4)
  }
  
  // argument resolver for curry5
  const curry5ResolveArg2 = (
    baseFunc, arg0, arg1, arg3, arg4,
  ) => function arg2Resolver(arg2) {
    return baseFunc(arg0, arg1, arg2, arg3, arg4)
  }
  
  // argument resolver for curry5
  const curry5ResolveArg3 = (
    baseFunc, arg0, arg1, arg2, arg4,
  ) => function arg3Resolver(arg3) {
    return baseFunc(arg0, arg1, arg2, arg3, arg4)
  }
  
  // argument resolver for curry5
  const curry5ResolveArg4 = (
    baseFunc, arg0, arg1, arg2, arg3,
  ) => function arg3Resolver(arg4) {
    return baseFunc(arg0, arg1, arg2, arg3, arg4)
  }
  
  const curry5 = function (baseFunc, arg0, arg1, arg2, arg3, arg4) {
    if (arg0 == __) {
      return curry5ResolveArg0(baseFunc, arg1, arg2, arg3, arg4)
    }
    if (arg1 == __) {
      return curry5ResolveArg1(baseFunc, arg0, arg2, arg3, arg4)
    }
    if (arg2 == __) {
      return curry5ResolveArg2(baseFunc, arg0, arg1, arg3, arg4)
    }
    if (arg3 == __) {
      return curry5ResolveArg3(baseFunc, arg0, arg1, arg2, arg4)
    }
    return curry5ResolveArg4(baseFunc, arg0, arg1, arg2, arg3)
  }
  
  const objectKeys = Object.keys
  
  const objectGetFirstKey = function (object) {
    for (const key in object) {
      return key
    }
    return undefined
  }
  
  const objectReduceAsync = async function (object, reducer, result, keys, index) {
    const keysLength = keys.length
    while (++index < keysLength) {
      const key = keys[index]
      result = reducer(result, object[key], key, object)
      if (isPromise(result)) {
        result = await result
      }
    }
    return result
  }
  
  const objectReduce = function (object, reducer, result) {
    const keys = objectKeys(object),
      keysLength = keys.length
    let index = -1
    if (result === undefined) {
      result = object[keys[++index]]
    }
    while (++index < keysLength) {
      const key = keys[index]
      result = reducer(result, object[key], key, object)
      if (isPromise(result)) {
        return result.then(curry5(objectReduceAsync, object, reducer, __, keys, index))
      }
    }
    return result
  }
  
  const mapReduceAsync = async function (
    map, reducer, result, mapEntriesIter,
  ) {
    for (const [key, value] of mapEntriesIter) {
      result = reducer(result, value, key, map)
      if (isPromise(result)) {
        result = await result
      }
    }
    return result
  }
  
  const mapReduce = function (map, reducer, result) {
    const mapEntriesIter = map.entries()
    if (result === undefined) {
      const firstIteration = mapEntriesIter.next()
      if (firstIteration.done) {
        return result
      }
      result = firstIteration.value[1]
    }
    for (const [key, value] of mapEntriesIter) {
      result = reducer(result, value, key, map)
      if (isPromise(result)) {
        return result.then(curry4(
          mapReduceAsync, map, reducer, __, mapEntriesIter))
      }
    }
    return result
  }
  
  const funcConcatSync = (
    funcA, funcB,
  ) => function pipedFunction(...args) {
    return funcB(funcA(...args))
  }
  
  const generatorFunctionReduce = (
    generatorFunction, reducer, result,
  ) => funcConcatSync(
    generatorFunction,
    curry3(iteratorReduce, __, reducer, result))
  
  const asyncGeneratorFunctionReduce = (
    asyncGeneratorFunction, reducer, result,
  ) => funcConcatSync(
    asyncGeneratorFunction,
    curry3(asyncIteratorReduce, __, reducer, result))
  
  const reducerConcat = (
    reducerA, reducerB,
  ) => function pipedReducer(result, item) {
    const intermediate = reducerA(result, item)
    return isPromise(intermediate)
      ? intermediate.then(curry2(reducerB, __, item))
      : reducerB(intermediate, item)
  }
  
  const genericReduce = function (args, reducer, result) {
    const collection = args[0]
    if (isArray(collection)) {
      return arrayReduce(collection, reducer, result)
    }
    if (typeof collection == 'function') {
      if (isGeneratorFunction(collection)) {
        return generatorFunctionReduce(collection, reducer, result)
      }
      if (isAsyncGeneratorFunction(collection)) {
        return asyncGeneratorFunctionReduce(collection, reducer, result)
      }
      return curryArgs3(
        genericReduce,
        __,
        args.length == 1
          ? reducerConcat(reducer, collection)
          : args.reduce(reducerConcat, reducer),
        result)
    }
    if (collection == null) {
      return result === undefined
        ? curry2(reducer, collection, __)
        : reducer(result, collection)
    }
  
    if (collection.constructor == Map) {
      return mapReduce(collection, reducer, result)
    }
    if (typeof collection[symbolIterator] == 'function') {
      return iteratorReduce(
        collection[symbolIterator](), reducer, result)
    }
    if (typeof collection[symbolAsyncIterator] == 'function') {
      return asyncIteratorReduce(
        collection[symbolAsyncIterator](), reducer, result)
    }
    if (typeof collection.reduce == 'function') {
      return collection.reduce(reducer, result)
    }
    if (typeof collection.chain == 'function') {
      return collection.chain(curry2(reducer, result, __))
    }
    if (typeof collection.flatMap == 'function') {
      return collection.flatMap(curry2(reducer, result, __))
    }
    if (collection.constructor == Object) {
      return objectReduce(collection, reducer, result)
    }
    return result === undefined
      ? curry2(reducer, collection, __)
      : reducer(result, collection)
  }
  
  const reduce = function (reducer, init) {
    if (typeof init == 'function') {
      return function reducing(...args) {
        const result = init(...args)
        return isPromise(result)
          ? result.then(curry3(genericReduce, args, reducer, __))
          : genericReduce(args, reducer, result)
      }
    }
    return curryArgs3(genericReduce, __, reducer, init)
  }
  
  const uniq = arr => {
    if (!isArray(arr)) throw Error('uniq(arr): arr is not an array')
  
    const seenSet = new Set()
    return reduce((acc, value) => {
      if (seenSet.has(value)) {
        return acc
      }
      seenSet.add(value)
      return [...acc, value]
    }, [])(arr)
  }
  
  export default uniq
  