import { Either, map as eitherMap, isLeft, isRight } from '@typed/either'
import { List, map as listMap } from '@typed/list'
import { Maybe, isJust, isNothing, map as maybeMap } from '@typed/maybe'
import { curry2 } from '@typed/functions'
import { isPromiseLike } from '@typed/logic'
/**
* Map over the value contained in a data structure.
* Works for `List`, `Maybe`, `Either`, and `PromiseLike` data strctures.
* @name map(f: (value: A, index: number) => B, list: List): Array
*/
export const map: Map = curry2(function map(f: (value: any) => any, list: any): any {
if (isJust(list) || isNothing(list)) return maybeMap(f, list)
if (isLeft(list) || isRight(list)) return eitherMap(f, list)
if (isPromiseLike(list)) return Promise.resolve(list.then(f))
return listMap(f, list)
})
export type Map = {
(f: (value: A, index: number) => B, list: List): Array
(f: (value: A) => B, maybe: Maybe): Maybe
(f: (value: A) => B, promise: PromiseLike): Promise
(f: (value: B) => C, either: Either): Either
(f: (value: A, index: number) => B): MapArity1
}
export type MapArity1 = {
(list: List): Array
(maybe: Maybe): Maybe
(promise: Promise): Promise
(either: Either): Either
}