import { Functor } from "./functor" ; import { Applicative } from "./applicative" ; export enum EitherTag { Left , Right } export type EitherMatch < A , B , K > = { left : ( a : A ) => K ; right : ( b : B ) => K ; } ; export abstract class Either < A , B > implements Applicative < B > { tag : EitherTag ; val : A | B ; abstract match < K > ( m ) ; abstract map < C > ( f ) ; abstract mapTo < C > ( c ) ; static of < A , B > ( b ) { return new Right ( b ) ; } of < B > ( b ) { return new Right ( b ) ; } ap < C > ( a ) { if ( isRight ( a ) ) { return this . map ( a . val ) ; } else { return < any > a ; } } lift < A , T1 , R > ( f , m ) ; lift < A , T1 , T2 , R > ( f , m1 , m2 ) ; lift < A , T1 , T2 , T3 , R > ( f , m1 , m2 , m3 ) ; lift < A > ( f , ... args ) { for ( let i = 0 ; i < args . length ; i ++ ) { if ( args [ i ] . tag === EitherTag . Left ) { return args [ i ] ; } } let rights = [ ] ; for ( let i = 0 ; i < args . length ; i ++ ) { rights . push ( args [ i ] . val ) ; } return new Right ( f ( ... rights ) ) ; } } export class Left < A , B > extends Either < A , B > { val : A ; tag : EitherTag = EitherTag . Left ; constructor ( a ) { super ( ) ; this . val = a ; } match < K > ( m ) { return m . left ( this . val ) ; } map < C > ( f ) { return new Left < A , C > ( this . val ) ; } mapTo < C > ( c ) { return new Left < A , C > ( this . val ) ; } } export class Right < A , B > extends Either < A , B > { val : B ; tag : EitherTag = EitherTag . Right ; constructor ( b ) { super ( ) ; this . val = b ; } match < K > ( m ) { return m . right ( this . val ) ; } map < C > ( f ) { return new Right < A , C > ( f ( this . val ) ) ; } mapTo < C > ( c ) { return new Right < A , C > ( c ) ; } } export function left < A > ( a ) { return new Left ( a ) ; } export function right < B > ( b ) { return new Right ( b ) ; } export function isLeft < A , B > ( a ) { return a . tag === EitherTag . Left ; } export function isRight < A , B > ( a ) { return a . tag === EitherTag . Right ; } export function fromEither < A , B > ( e ) { return e . val ; }