import * as Maybe from './maybe'; export type Err = { kind: 'Err'; error: Error; }; export type Ok = { kind: 'Ok'; value: Value; }; export type Result = Ok | Err; /* Creates an Ok value */ export function Ok(value: Value): Result { return { kind: 'Ok', value: value, }; } /* Creates an Err value */ export function Err(error: Error): Result { return { kind: 'Err', error: error, }; } /* If result is Ok, return the value inside it. Otherwise return the default value provided; */ export function withDefault( value: Value, result: Result ): Value { switch (result.kind) { case 'Ok': return result.value; default: return value; } } /* When both error and Ok are the same value, return the inner value of whichever is contained. */ export function either(result: Result) { switch (result.kind) { case 'Ok': return result.value; default: return result.error; } } /* Turns Ok into Just, Err into Nothing */ export function toMaybe( result: Result ): Maybe.Maybe { switch (result.kind) { case 'Ok': return Maybe.Just(result.value); default: return Maybe.Nothing(); } } /* Turns Just into Ok, Nothing into Err with the default value provided. */ export function fromMaybe( error: Error, maybe: Maybe.Maybe ): Result { switch (maybe.kind) { case 'Just': return Ok(maybe.value); default: return Err(error); } } /* If result is Ok, apply a function to it and return a Ok containing the new value. Otherwise return Err. */ export function map( func: (val: A) => Value, result: Result ): Result { switch (result.kind) { case 'Ok': return Ok(func(result.value)); default: return result; } } /* If all results are Ok, apply a function to them and return a Ok containing the new value. Otherwise return the first Err encountered. */ export function map2( func: (firstResult: A, secondResult: B) => Value, firstResult: Result, secondResult: Result ): Result { switch (firstResult.kind) { case 'Ok': switch (secondResult.kind) { case 'Ok': return Ok(func(firstResult.value, secondResult.value)); default: return secondResult; } default: return firstResult; } } /* If all results are Ok, apply a function to them and return a Ok containing the new value. Otherwise return the first Err encountered. */ export function map3( func: (firstResult: A, secondResult: B, thirdResult: C) => Value, firstResult: Result, secondResult: Result, thirdResult: Result ): Result { switch (firstResult.kind) { case 'Ok': switch (secondResult.kind) { case 'Ok': switch (thirdResult.kind) { case 'Ok': return Ok( func( firstResult.value, secondResult.value, thirdResult.value ) ); default: return thirdResult; } default: return secondResult; } default: return firstResult; } } /* If result is Err, apply a function to it and return a Err containing the new value. Otherwise return Ok. */ export function mapError( func: (val: ErrorA) => ErrorB, result: Result ): Result { switch (result.kind) { case 'Err': return Err(func(result.error)); default: return result; } } /* If the result is Ok, apply a function that turns things into a result to it. Otherwise return Err. */ export function andThen( func: (value: A) => Result, result: Result ): Result { switch (result.kind) { case 'Ok': return func(result.value); default: return result; } }