import { Maybe , Just , Nothing } from './Maybe' ; import { ApKind , ofAp } from './pointfree/ap' ; import { ofSymbol } from './pointfree/do' ; import { ReplaceFirst , Type , URIS } from './pointfree/hkt' ; export type EitherPatterns < L , R , T > = { Left : ( l : L ) => T ; Right : ( r : R ) => T ; } | { _ : ( ) => T ; } ; export const EITHER_URI = 'Either' ; export type EITHER_URI = typeof EITHER_URI ; declare module './pointfree/hkt' { export interface URI2HKT < Types extends any [ ] > { [ EITHER_URI ] : Either < Types [ 1 ] , Types [ 0 ] > ; } } export interface Either < L , R > { readonly _URI : EITHER_URI ; readonly _A : [ R , L ] ; [ Symbol . iterator ] : ( ) => Iterator < Either < L , R > , R , any > ; [ ofSymbol ] : EitherTypeRef [ 'of' ] ; /** Returns true if `this` is `Left`, otherwise it returns false */ isLeft ( ) : this is Left < L , never > ; /** Returns true if `this` is `Right`, otherwise it returns false */ isRight ( ) : this is Right < R , never > ; toJSON ( ) : L | R ; inspect ( ) : string ; toString ( ) : string ; /** Given two functions, maps the value inside `this` using the first if `this` is `Left` or using the second one if `this` is `Right`.
     * If both functions return the same type consider using `Either#either` instead
     */ bimap < L2 , R2 > ( f , g ) : Either < L2 , R2 > ; /** Maps the `Right` value of `this`, acts like an identity if `this` is `Left` */ map < R2 > ( f ) : Either < L , R2 > ; /** Maps the `Left` value of `this`, acts like an identity if `this` is `Right` */ mapLeft < L2 > ( f ) : Either < L2 , R > ; /** Applies a `Right` function over a `Right` value. Returns `Left` if either `this` or the function are `Left` */ ap < R2 > ( other ) : Either < L , R2 > ; /** Compares `this` to another `Either`, returns false if the constructors or the values inside are different, e.g. `Right(5).equals(Left(5))` is false */ equals ( other ) : boolean ; /** Transforms `this` with a function that returns an `Either`. Useful for chaining many computations that may fail */ chain < R2 > ( f ) : Either < L , R2 > ; /** The same as Either#chain but executes the transformation function only if the value is Left. Useful for recovering from errors */ chainLeft < L2 > ( f ) : Either < L2 , R > ; /** Flattens nested Eithers. `e.join()` is equivalent to `e.chain(x => x)` */ join < R2 > ( this ) : Either < L , R2 > ; /** Returns the first `Right` between `this` and another `Either` or the `Left` in the argument if both `this` and the argument are `Left` */ alt ( other ) : Either < L , R > ; /** Takes a reducer and an initial value and returns the initial value if `this` is `Left` or the result of applying the function to the initial value and the value inside `this` */ reduce < T > ( reducer , initialValue ) : T ; /** Returns `this` if it's a `Left`, otherwise it returns the result of applying the function argument to `this` and wrapping it in a `Right` */ extend < R2 > ( f ) : Either < L , R2 > ; /** Returns the value inside `this` if it's a `Right` or either throws the value or a generic exception depending on whether the value is an Error */ unsafeCoerce ( ) : R ; /** Structural pattern matching for `Either` in the form of a function */ caseOf < T > ( patterns ) : T ; /** Returns the value inside `this` if it\'s `Left` or a default value if `this` is `Right` */ leftOrDefault ( defaultValue ) : L ; /** Returns the value inside `this` if it\'s `Right` or a default value if `this` is `Left` */ orDefault ( defaultValue ) : R ; /** Lazy version of `orDefault`. Takes a function that returns the default value, that function will be called only if `this` is `Left` */ orDefaultLazy ( getDefaultValue ) : R ; /** Lazy version of `leftOrDefault`. Takes a function that returns the default value, that function will be called only if `this` is `Right` */ leftOrDefaultLazy ( getDefaultValue ) : L ; /** Runs an effect if `this` is `Left`, returns `this` to make chaining other methods possible */ ifLeft ( effect ) : this ; /** Runs an effect if `this` is `Right`, returns `this` to make chaining other methods possible */ ifRight ( effect ) : this ; /** Constructs a `Just` with the value of `this` if it\'s `Right` or a `Nothing` if `this` is `Left` */ toMaybe ( ) : Maybe < R > ; /** Constructs a `Just` with the value of `this` if it\'s `Left` or a `Nothing` if `this` is `Right` */ leftToMaybe ( ) : Maybe < L > ; /** Given two map functions, maps using the first if `this` is `Left` or using the second one if `this` is `Right`.
     * If you want the functions to return different types depending on the either you may want to use `Either#bimap` instead
     * */ either < T > ( ifLeft , ifRight ) : T ; /** Extracts the value out of `this` */ extract ( ) : this extends Right < R , never > ? R : this extends Left < L , never > ? L : L | R ; /** Returns `Right` if `this` is `Left` and vice versa */ swap ( ) : Either < R , L > ; traverse < URI extends URIS , AP extends ApKind < any , any > = ApKind < URI , any > > ( of , f ) : Type < URI , ReplaceFirst < AP [ '_A' ] , Either < L , AP [ '_A' ] [ 0 ] > > > ; sequence < Ap extends ApKind < any , any > > ( this , of ) : Type < Ap [ '_URI' ] , ReplaceFirst < Ap [ '_A' ] , Either < L , Ap [ '_A' ] [ 0 ] > > > ; 'fantasy-land/traverse' < URI extends URIS , AP extends ApKind < any , any > = ApKind < URI , any > > ( of , f ) : Type < URI , ReplaceFirst < AP [ '_A' ] , Either < L , AP [ '_A' ] [ 0 ] > > > ; 'fantasy-land/sequence' < Ap extends ApKind < any , any > > ( this , of ) : Type < Ap [ '_URI' ] , ReplaceFirst < Ap [ '_A' ] , Either < L , Ap [ '_A' ] [ 0 ] > > > ; 'fantasy-land/bimap' < L2 , R2 > ( f , g ) : Either < L2 , R2 > ; 'fantasy-land/map' < R2 > ( f ) : Either < L , R2 > ; 'fantasy-land/ap' < R2 > ( other ) : Either < L , R2 > ; 'fantasy-land/equals' ( other ) : boolean ; 'fantasy-land/chain' < R2 > ( f ) : Either < L , R2 > ; 'fantasy-land/alt' ( other ) : Either < L , R > ; 'fantasy-land/reduce' < T > ( reducer , initialValue ) : T ; 'fantasy-land/extend' < R2 > ( f ) : Either < L , R2 > ; } interface EitherTypeRef { /** Takes a value and wraps it in a `Right` */ of < L , R > ( value ) : Either < L , R > ; /** Takes a list of `Either`s and returns a list of all `Left` values */ lefts < L , R > ( list ) : L [ ] ; /** Takes a list of `Either`s and returns a list of all `Right` values */ rights < L , R > ( list ) : R [ ] ; /** Calls a function and returns a `Right` with the return value or an exception wrapped in a `Left` in case of failure */ encase < L extends Error , R > ( throwsF ) : Either < L , R > ; /** Turns a list of `Either`s into an `Either` of list */ sequence < L , R > ( eithers ) : Either < L , R [ ] > ; isEither < L , R > ( x ) : x is Either < L , R > ; 'fantasy-land/of' < L , R > ( value ) : Either < L , R > ; } export const Either = { of < L , R > ( value ) { return right ( value ) ; } , lefts < L , R > ( list ) { let result = [ ] ; for ( const x of list ) { if ( x . isLeft ( ) ) { result . push ( x . extract ( ) ) ; } } return result ; } , rights < L , R > ( list ) { let result = [ ] ; for ( const x of list ) { if ( x . isRight ( ) ) { result . push ( x . extract ( ) ) ; } } return result ; } , encase < L extends Error , R > ( throwsF ) { try { return right ( throwsF ( ) ) ; } catch ( e ) { return left ( e ) ; } } , sequence < L , R > ( eithers ) { let res = [ ] ; for ( const e of eithers ) { if ( e . isLeft ( ) ) { return e ; } res . push ( e . extract ( ) as R ) ; } return right ( res ) ; } , isEither < L , R > ( x ) { return x instanceof Left || x instanceof Right ; } , 'fantasy-land/of' < L , R > ( value ) { return Either . of ( value ) ; } } ; class Right < R , L = never > implements Either < L , R > { private _ = 'R' ; readonly _URI ! : EITHER_URI ; readonly _A ! : [ R , L ] ; constructor ( private __value ) { } * [ Symbol . iterator ] ( ) { return ( yield this ) as R ; } [ ofSymbol ] = Either . of ; isLeft ( ) { return false ; } isRight ( ) { return true ; } 'fantasy-land/traverse' < URI extends URIS , AP extends ApKind < any , any > = ApKind < URI , any > > ( of , f ) { return this . traverse ( of , f ) ; } traverse < URI extends URIS , AP extends ApKind < any , any > = ApKind < URI , any > > ( _of , f ) { const result = f ( this . __value ) ; return result . map ( right ) ; } 'fantasy-land/sequence' < Ap extends ApKind < any , any > > ( this , of ) { return this . sequence ( of ) ; } sequence < Ap extends ApKind < any , any > > ( this , _of ) { return ( this as any ) . __value . map ( right ) ; } toJSON ( ) { return this . __value ; } inspect ( ) { return `Right(${ JSON . stringify ( this . __value ) })` ; } toString ( ) { return this . inspect ( ) ; } bimap < L2 , R2 > ( _f , g ) { return right ( g ( this . __value ) ) ; } map < R2 > ( f ) { return right ( f ( this . __value ) ) ; } mapLeft < L2 > ( _ ) { return this as any ; } ap < R2 > ( other ) { return other . isRight ( ) ? this . map ( other . extract ( ) ) : ( other as any ) ; } equals ( other ) { return other . isRight ( ) ? this . __value === other . extract ( ) : false ; } chain < R2 > ( f ) { return f ( this . __value ) ; } chainLeft < L2 > ( _ ) { return this as any ; } join < R2 > ( this ) { return this . __value as any ; } alt ( _ ) { return this ; } reduce < T > ( reducer , initialValue ) { return reducer ( initialValue , this . __value ) ; } extend < R2 > ( f ) { return right ( f ( this ) ) ; } unsafeCoerce ( ) { return this . __value ; } caseOf < T > ( patterns ) { return '_' in patterns ? patterns . _ ( ) : patterns . Right ( this . __value ) ; } leftOrDefault ( defaultValue ) { return defaultValue ; } orDefault ( _ ) { return this . __value ; } orDefaultLazy ( _ ) { return this . __value ; } leftOrDefaultLazy ( getDefaultValue ) { return getDefaultValue ( ) ; } ifLeft ( _ ) { return this ; } ifRight ( effect ) { return effect ( this . __value ) , this ; } toMaybe ( ) { return Just ( this . __value ) ; } leftToMaybe ( ) { return Nothing ; } either < T > ( _ , ifRight ) { return ifRight ( this . __value ) ; } extract ( ) { return this . __value as any ; } swap ( ) { return left ( this . __value ) ; } 'fantasy-land/bimap' < L2 , R2 > ( f , g ) { return this . bimap ( f , g ) ; } 'fantasy-land/map' < R2 > ( f ) { return this . map ( f ) ; } 'fantasy-land/ap' < R2 > ( other ) { return this . ap ( other ) ; } 'fantasy-land/equals' ( other ) { return this . equals ( other ) ; } 'fantasy-land/chain' < R2 > ( f ) { return this . chain ( f ) ; } 'fantasy-land/alt' ( other ) { return this . alt ( other ) ; } 'fantasy-land/reduce' < T > ( reducer , initialValue ) { return this . reduce ( reducer , initialValue ) ; } 'fantasy-land/extend' < R2 > ( f ) { return this . extend ( f ) ; } } Right . prototype . constructor = Either as any ; class Left < L , R = never > implements Either < L , R > { private _ = 'L' ; readonly _URI ! : EITHER_URI ; readonly _A ! : [ R , L ] ; constructor ( private __value ) { } * [ Symbol . iterator ] ( ) { return ( yield this ) as R ; } [ ofSymbol ] = Either . of ; isLeft ( ) { return true ; } isRight ( ) { return false ; } toJSON ( ) { return this . __value ; } inspect ( ) { return `Left(${ JSON . stringify ( this . __value ) })` ; } toString ( ) { return this . inspect ( ) ; } bimap < L2 , R2 > ( f , _g ) { return left ( f ( this . __value ) ) ; } 'fantasy-land/traverse' < URI extends URIS , AP extends ApKind < any , any > = ApKind < URI , any > > ( of , f ) { return this . traverse ( of , f ) ; } traverse < URI extends URIS , AP extends ApKind < any , any > = ApKind < URI , any > > ( of , _f ) { return of ( this ) as any ; } 'fantasy-land/sequence' < Ap extends ApKind < any , any > > ( this , of ) { return this . sequence ( of ) ; } sequence < Ap extends ApKind < any , any > > ( this , of ) { return of ( this ) ; } map < R2 > ( _ ) { return this as any ; } mapLeft < L2 > ( f ) { return left ( f ( this . __value ) ) ; } ap < R2 > ( other ) { return other . isLeft ( ) ? other : ( this as any ) ; } equals ( other ) { return other . isLeft ( ) ? other . extract ( ) === this . __value : false ; } chain < R2 > ( _ ) { return this as any ; } chainLeft < L2 > ( f ) { return f ( this . __value ) ; } join < R2 > ( this ) { return this as any ; } alt ( other ) { return other ; } reduce < T > ( _ , initialValue ) { return initialValue ; } extend < R2 > ( _ ) { return this as any ; } unsafeCoerce ( ) { if ( this . __value instanceof Error ) { throw this . __value ; } throw new Error ( 'Either#unsafeCoerce was ran on a Left' ) ; } caseOf < T > ( patterns ) { return '_' in patterns ? patterns . _ ( ) : patterns . Left ( this . __value ) ; } leftOrDefault ( _ ) { return this . __value ; } orDefault ( defaultValue ) { return defaultValue ; } orDefaultLazy ( getDefaultValue ) { return getDefaultValue ( ) ; } leftOrDefaultLazy ( _ ) { return this . __value ; } ifLeft ( effect ) { return effect ( this . __value ) , this ; } ifRight ( _ ) { return this ; } toMaybe ( ) { return Nothing ; } leftToMaybe ( ) { return Just ( this . __value ) ; } either < T > ( ifLeft , _ ) { return ifLeft ( this . __value ) ; } extract ( ) { return this . __value as any ; } swap ( ) { return right ( this . __value ) ; } 'fantasy-land/bimap' < L2 , R2 > ( f , g ) { return this . bimap ( f , g ) ; } 'fantasy-land/map' < R2 > ( f ) { return this . map ( f ) ; } 'fantasy-land/ap' < R2 > ( other ) { return this . ap ( other ) ; } 'fantasy-land/equals' ( other ) { return this . equals ( other ) ; } 'fantasy-land/chain' < R2 > ( f ) { return this . chain ( f ) ; } 'fantasy-land/alt' ( other ) { return this . alt ( other ) ; } 'fantasy-land/reduce' < T > ( reducer , initialValue ) { return this . reduce ( reducer , initialValue ) ; } 'fantasy-land/extend' < R2 > ( f ) { return this . extend ( f ) ; } } Left . prototype . constructor = Either as any ; const left = < L , R = never > ( value ) : Either < L , R > => new Left ( value ) ; const right = < R , L = never > ( value ) : Either < L , R > => new Right ( value ) ; export { left as Left , right as Right } ; export type IsLeft = { < L , R > ( either ) : either is Either < L , never > ; } ; export type IsRight = { < L , R > ( either ) : either is Either < never , R > ; } ; export const isLeft = < L , R > ( either ) : either is Either < L , never > => either . isLeft ( ) ; export const isRight = < L , R > ( either ) : either is Either < never , R > => either . isRight ( ) ;