import type { FunctionN } from "../Function";
import type { IO } from "../IO";
import { fromIO } from "./constructors";
import type { LazyPromise } from "./model";
import { chain } from "./monad";
/*
* -------------------------------------------
* LazyPromise Combinators
* -------------------------------------------
*/
/**
* ```haskell
* delay_ :: (LazyPromise a, Number) -> LazyPromise a
* ```
*
* Delays a `LazyPromise` by the provided number of milliseconds.
*
* @category Combinators
* @since 1.0.0
*/
export const delay_ = (ma: LazyPromise, ms: number): LazyPromise => () =>
new Promise((resolve) => {
setTimeout(() => {
ma().then(resolve);
}, ms);
});
/**
* ```haskell
* delay :: Number -> LazyPromise a -> LazyPromise a
* ```
*
* Delays a `LazyPromise` by the provided number of milliseconds.
*
* @category Combinators
* @since 1.0.0
*/
export const delay = (ms: number) => (ma: LazyPromise): LazyPromise => delay_(ma, ms);
/**
* ```haskell
* fromIOK :: ((a, b, ...) -> IO c) -> ((a, b, ...) -> LazyPromise c)
* ```
*
* Lifts an uncurried, n-ary function returning an `IO` to one that returns a `LazyPromise`
*
* @category Combinators
* @since 1.0.0
*/
export const fromIOK = , B>(f: FunctionN>): FunctionN> => (
...a
) => fromIO(f(...a));
/**
* ```haskell
* chainIOK :: (a -> IO b) -> LazyPromise a -> LazyPromise b
* ```
*
* Lifts a unary function that takes an `a` and returns an `IO b` to one that takes a `LazyPromise a` and returns a `LazyPromise b`
* @category Combinators
* @since 1.0.0
*/
export const chainIOK = (f: (a: A) => IO): ((ma: LazyPromise) => LazyPromise) => chain(fromIOK(f));