import { Maybe } from "./maybe" ; import { Either } from "./either" ; import { mixin } from "./utils" ; function arrayMap < A , B > ( f , as ) { let newArr = [ ] ; for ( const a of as ) { newArr . push ( f ( a ) ) ; } return newArr ; } function repeat < A > ( a , length ) { let newArr = [ ] ; for ( let i = 0 ; i < length ; ++ i ) { newArr . push ( a ) ; } return newArr ; } export interface Functor < A > { map < B > ( f ) : Functor < B > ; mapTo < B > ( b ) : Functor < B > ; } export type AnyFunctor < A > = A [ ] | Functor < A > ; export abstract class AbstractFunctor < A > implements Functor < A > { abstract map < B > ( f ) ; mapTo < B > ( b ) { return this . map ( ( _ ) => b ) ; } } export function functor ( constructor ) { if ( ! ( "map" in constructor . prototype ) ) { throw new TypeError ( "Can't derive functor. `map` method missing." ) ; } mixin ( constructor , [ AbstractFunctor ] ) ; } export function map < A , B > ( f , functor ) ; export function map < A , B , C > ( f , functor ) ; export function map < A , B > ( f , functor ) ; export function map < A , B > ( f , functor ) ; export function map < A , B > ( f , functor ) ; export function map < A , B > ( f , functor ) { if ( Array . isArray ( functor ) ) { return arrayMap ( f , functor ) ; } else { return functor . map ( f ) ; } } export function mapTo < A , B > ( b , functor ) ; export function mapTo < A , B , C > ( c , functor ) ; export function mapTo < A , B > ( b , functor ) ; export function mapTo < A , B > ( b , functor ) ; export function mapTo < A , B > ( b , functor ) ; export function mapTo < A , B > ( b , functor ) { if ( Array . isArray ( functor ) ) { return repeat ( b , functor . length ) ; } else { return functor . mapTo ( b ) ; } } export function mapMap ( f , functor ) { return map ( ( fa ) => map ( f , fa ) , functor ) ; }