import { curry } from 'lodash' ; export interface Ok < T > { tag : 'ok' ; value : T ; } export interface Err < E > { tag : 'err' ; error : E ; } export type Result < T , E > = Ok < T > | Err < E > ; export function asOk < T > ( value ) { return { tag : 'ok' , value , } ; } export function asErr < T > ( error ) { return { tag : 'err' , error , } ; } export function isOk < T , E > ( result ) { return result . tag === 'ok' ; } export function isErr < T , E > ( result ) { return ! isOk ( result ) ; } export function tryAsResult < T , E > ( fn ) { try { return asOk ( fn ( ) ) ; } catch ( e ) { return asErr ( e ) ; } } export async function promiseResult < T , E > ( future ) { try { return asOk ( await future ) ; } catch ( e ) { return asErr ( e ) ; } } export async function unwrapPromise < T , E > ( future ) { return future . catch ( ( ex ) => ex ) . then ( ( result ) => map ( result , ( value ) => Promise . resolve ( value ) , ( err ) => Promise . reject ( err ) ) ) ; } export function unwrap < T , E > ( result ) { return isOk ( result ) ? result . value : result . error ; } export function either < T , E > ( result , onOk , onErr ) { map < T , E , void > ( result , onOk , onErr ) ; return result ; } export async function eitherAsync < T , E > ( result , onOk , onErr ) { return await map < T , E , Promise < void > > ( result , onOk , onErr ) ; } export function map < T , E , Resolution > ( result , onOk , onErr ) { return isOk ( result ) ? onOk ( result . value ) : onErr ( result . error ) ; } export const mapR = curry ( function < T , E , Resolution > ( onOk , onErr , result ) : Resolution { return map ( result , onOk , onErr ) ; } ) ; export const mapOk = curry ( function < T , T2 , E > ( onOk , result ) : Result < T2 , E > { return isOk ( result ) ? onOk ( result . value ) : result ; } ) ; export const mapErr = curry ( function < T , E , E2 > ( onErr , result ) : Result < T , E2 > { return isOk ( result ) ? result : onErr ( result . error ) ; } ) ;