/** @module functor-helpers.ts */ import { HKT, Type, URIS } from 'fp-ts/lib/HKT' import { pushArray } from './array/pushArray' import { unshiftArray } from './array/unshiftArray' import { untypedCurry } from './function/untypedCurry' import { Append, Concat, Concattable, Filterable, Function1, Functor, Predicate, Prepend, Pushable, ValueOf } from './helper-types' interface ConcatCurried { ( item: B ): Concat < A, B > ( item: B ): B extends any[] ? Array< ValueOf | ValueOf> : Concat < A, [B] > ( item: B ): Array < ValueOf | ValueOf < B >> } export function concat( acc: A, item: B ): Concat export function concat( acc: A ): ConcatCurried export function concat( acc: A, item: B ): B extends any[] ? Array< ValueOf | ValueOf> : Concat export function concat( acc: A ): ConcatCurried export function concat( acc: A, item: B ): Array< ValueOf | ValueOf> export function concat( acc: A ): ConcatCurried export function concat( acc: A, item: B ): Array< ValueOf | ValueOf> export function concat( acc: A ): ( item: B ) => Array< ValueOf | ValueOf> export function concat( acc: ConcatArray , item: A ): ConcatArray export function concat( acc: ConcatArray ): ( item: A ) => ConcatArray export function concat( acc: Concattable , item: A ): Concattable export function concat( acc: Concattable ): ( item: A ) => Concattable export function concat( arr: A[], item: A ): A[] export function concat( arr: A[] ): ( item: A ) => A[] export function concat, B extends any >( arr: A ): ( item: B ) => Array /** * Calls `concat` on an array or a concattable. Also typed to work well with tuples. * * @param arr * @param item */ export function concat( ...args ) { return untypedCurry( ( a, b ) => a.concat( b ) )( ...args ) } /** * Flips the order of parameters of `concat` which calls `concat` * on an array or a concattable. Also typed to work well with tuples. * @param item * @param arr */ export function flipConcat( item: A, acc: B ): Concat export function flipConcat( item: A ): ( acc: B ) => Concat export function flipConcat( item: A, acc: B ): A extends any[] ? Array< ValueOf | ValueOf> : Concat export function flipConcat( item: A ): ( acc: B ) => A extends any[] ? Array< ValueOf | ValueOf> : Concat export function flipConcat( item: A, acc: B ): Array< ValueOf | ValueOf> export function flipConcat( item: A ): ( acc: B ) => Array< ValueOf | ValueOf> export function flipConcat( item: A, acc: ConcatArray ): ConcatArray export function flipConcat( item: A ): ( acc: ConcatArray ) => ConcatArray export function flipConcat( item: A, acc: Concattable ): Concattable export function flipConcat( item: A ): ( acc: Concattable ) => Concattable export function flipConcat( item: A , arr: A[] ): A[] export function flipConcat( item: A ): ( arr: A[] ) => A[] export function flipConcat, B extends any >( item: B ): ( arr: A ) => Array export function flipConcat( ...args ) { return untypedCurry( ( a , b ) => b.concat( a ) )( ...args ) } declare module 'fp-ts/lib/HKT' { interface URI2HKT { 'Array': A[], } } export function push( acc: A, item: B ): Append export function push( acc: A ): ( item: B ) => Append export function push( acc: A, item: B ): Array|B> export function push( acc: A ): ( item: B ) => Array|B> export function push( acc: Pushable, item: A ): Pushable < A > export function push( acc: Pushable ): ( item: A ) => Pushable < A > export function push( ...args ) { return untypedCurry( ( acc, item ) => Array.isArray( acc ) ? pushArray( acc, item ) : acc.push( item ), )( ...args ) } export function unshift( acc: A, item: B ): Prepend export function unshift( acc: A ): ( item: B ) => Prepend export function unshift( acc: A, item: B ): Array|B> export function unshift( acc: A ): ( item: B ) => Array|B> export function unshift( ...args ) { return untypedCurry( ( acc, item ) => Array.isArray( acc ) ? unshiftArray( acc, item ) : acc.unshift( item ), )( ...args ) } interface IPrepend { ( acc: A ): Prepend ( acc: A ): Array|B> } export function prepend( item: B, acc: A ): Prepend export function prepend( item: B, acc: A ): Array|B> export function prepend( item: B ): IPrepend export function prepend( ...args ) { return untypedCurry( ( item, acc ) => acc.concat( [ item ] ), )( ...args ) } /** * Takes a function and a filterable and returns said filterable after transformation * (a -> bool) -> c a -> c a */ export function filter( fn: Predicate, functor: F ): F export function filter( fn: Predicate ): ( functor: F ) => F // export function filter( fn: Predicate, functor: HKT & Filterable ): Type // export function filter( fn: Predicate ): ( functor: HKT & Filterable ) => Type export function filter( ...args ) { return untypedCurry( ( fn, filterable ) => filterable.filter( fn ) )( ...args ) } /** * Takes a function and a functor and lifts function over values in functor * (a -> b) -> f a -> f b */ export function map( fn: Function1, functor: HKT & Functor ): Type export function map( fn: Function1 ): ( functor: HKT & Functor ) => Type export function map( ...args ) { return untypedCurry( ( fn, functor ) => functor.map( fn ) )( ...args ) } interface Reduce { ( initial: V ): ( functor: ( HKT & Functor ) | A[] ) => V ( initial: V , functor: ( HKT & Functor ) | A[] ): V } export function reduce( fn: ( acc: V, item: A ) => V, initial: V, functor: ( HKT & Functor ) | A[] ): V export function reduce( fn: ( acc: V, item: A ) => V, initial: V ): ( functor: ( HKT & Functor ) | A[] ) => V export function reduce( fn: ( acc: V, item: A ) => V ): Reduce< A, V, F > export function reduce( ...args ) { return untypedCurry( ( fn, initial, functor ) => functor.reduce( fn, initial ), )( ...args ) } interface Fold { ( fn: ( acc: V, item: A ) => V ): ( functor: ( HKT & Functor ) | A[] ) => V ( fn: ( acc: V, item: A ) => V, functor: ( HKT & Functor ) | A[] ): V } export function fold( initial: V, fn: ( acc: V, item: A ) => V, functor: ( HKT & Functor ) | A[] ): V export function fold( initial: V, fn: ( acc: V, item: A ) => V ): ( functor: ( HKT & Functor ) | A[] ) => V export function fold( initial: V ): Fold< A, V, F > export function fold( ...args ) { return untypedCurry( ( fn, initial, functor ) => Array.isArray( functor ) ? functor.reduce( fn, initial ) : functor.fold( initial, fn ), )( ...args ) }