/**
 * An element in the DAG
 */
export interface Value {
    readonly _tag: 'value';
    /**
     * The next step in the plan.
     */
    next: Node | null;
}
/**
 * A fork node defines a branching in the DAG. A fork node can
 * have zero or more next nodes.
 */
export interface Fork {
    readonly _tag: 'fork';
    next: Node[];
}
/**
 * An join node is a node to indicate a joining of the branches
 * created by the split node.
 */
export interface Join {
    readonly _tag: 'join';
    next: Node | null;
}
export type Node = Value | Fork | Join;
export declare function isValue(n: Node): n is Value;
export declare function isFork(n: Node): n is Fork;
export declare function reduce<T, V extends Value>(node: Node | null, reducer: (acc: T, v: V) => T, initial: T): T;
export declare function mapReduce<T>(root: Node | null, initial: T, mapper: (v: Value, acc: T) => T, reducer: (acc: T[]) => T): T;
export declare function mapReduce<T, V extends Value>(root: Node | null, initial: T, mapper: (v: V, acc: T) => T, reducer: (acc: T[]) => T): T;
export declare function reverse<N extends Node>(root: N | null): N | null;
/**
 * Find the first element matching the predicate
 */
export declare function find(root: Node | null, condition: (v: Value) => boolean): Value | null;
export declare function find<V extends Value>(root: Node | null, condition: (v: V) => boolean): V | null;
/**
 * Returns a compact string representation of the plan, useful for debugging
 * and for comparing between results.
 *
 * The string representation of a plan works as follows
 * - `-` indicates a node in the plan
 * - `+` indicates a fork
 * - `~` indicates a branch in the fork
 * Depth of the node is indicated using indentation (2 spaces per level)
 *
 * For example, the following output:
 * - a
 * + ~ - b
 *     - c
 *   ~ - d
 * - f
 *
 * Indicates a plan that first performs an action 'a', then a fork is reached, where the first
 * branch will perform action 'b', then action 'c', and the second branch will perform action 'd'.
 * Finally the plan will perform action 'f'.
 *
 * Labels for the nodes are obtained by calling the toStr function on every value node.
 *
 * The `toStr` should not return new lines for the representation to work properly
 */
export declare function toString(root: Node | null, toStr: (v: Value) => string): string;
export declare function toString<V extends Value>(root: Node | null, toStr: (v: V) => string): string;
export declare function createFork(next?: Node[]): Fork;
export declare function createJoin(next?: Node | null): Join;
export declare function createValue<T extends object>(data: T): Value & T;
export declare const Node: {
    value: typeof createValue;
    fork: typeof createFork;
    join: typeof createJoin;
};
