// @flow import type { Maybe } from './Maybe' import type { Applicative } from './Applicative' import type { Traversable } from './Traversable' import type { Tuple } from './Tuple' import { HKT } from './HKT' import * as maybe from './Maybe' import { inj } from './Tuple' import { sequence } from './Traversable' import { constant } from './Fun' // This class identifies data structures which can be _unfolded_, // generalizing `unfoldr` on arrays. export interface Unfoldable { unfoldr(f: (b: B) => Maybe>, b: B): HKT } // Replicate a value some natural number of times. export function replicate(unfoldable: Unfoldable, n: number, a: A): HKT { function step(n: number): Maybe> { return n <= 0 ? maybe.Nothing : maybe.of(inj([a, n - 1])) } return unfoldable.unfoldr(step, n) } // Perform an Applicative action `n` times, and accumulate all the results. export function replicateA( applicative: Applicative, unfoldableTraversable: Unfoldable & Traversable, n: number, ma: HKT ): HKT> { return sequence(applicative, unfoldableTraversable, replicate(unfoldableTraversable, n, ma)) } // The container with no elements - unfolded with zero iterations. export function none(unfoldable: Unfoldable): HKT { return unfoldable.unfoldr(constant(maybe.Nothing), undefined) } export function singleton(unfoldable: Unfoldable, a: A): HKT { return replicate(unfoldable, 1, a) }