Last active
June 27, 2021 13:50
-
-
Save moatorres/e742cd698c304a7b0ecf335ee8fa7c9a to your computer and use it in GitHub Desktop.
Result monad in JS/Node (without classes)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Result } from './Result' | |
const okLog = (value) => `${value}, great` | |
const okRes = Result.ok('All good') | |
console.log('type:', okRes.type) | |
console.log('isOk?', okRes.isOk()) | |
console.log('isErr?', okRes.isErr()) | |
console.log('ok:', okRes.ok().unwrapOr('Okey dokey')) | |
console.log('err:', okRes.err().isOk()) | |
console.log('unwrap:', okRes.unwrap()) | |
console.log('match:', okRes.match({ ok: () => 'Big win' })) | |
console.log('unwrapOr:', okRes.unwrapOr('Oops')) | |
console.log('unwrapOrElse:', okRes.unwrapOrElse(okLog)) | |
console.log('map:', okRes.map(okLog).unwrap()) | |
console.log('mapErr:', okRes.mapErr(okLog).unwrap()) | |
console.log('andThen:', okRes.andThen(okLog)) | |
console.log('orElse:', okRes.orElse(okLog).unwrap()) | |
const errLog = () => 'Broke up' | |
const erroRes = Result.fail('Not ideal') | |
console.log('type:', erroRes.type) | |
console.log('isOk?', erroRes.isOk()) | |
console.log('isErr?', erroRes.isErr()) | |
console.log('ok:', erroRes.ok().unwrapOr('Really not ok')) | |
console.log('err:', erroRes.err().unwrapErr()) | |
console.log('unwrapErr:', erroRes.unwrapErr()) | |
console.log('match:', erroRes.match({ err: () => 'Huge mistake' })) | |
console.log('unwrapOr:', erroRes.unwrapOr('WTF?')) | |
console.log('unwrapOrElse:', erroRes.unwrapOrElse(errLog)) | |
console.log('map:', erroRes.map('Oops?').unwrapErr()) | |
console.log('mapErr:', erroRes.mapErr(errLog).unwrapErr()) | |
console.log('andThen:', erroRes.andThen('Boom').unwrapErr()) | |
console.log('orElse:', erroRes.orElse(errLog)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const makeReadOnly = (value) => Object.freeze(value) | |
const ResultType = { | |
Ok: Symbol(':ok'), | |
Err: Symbol(':err'), | |
} | |
const Ok = (val) => makeReadOnly({ | |
type: ResultType.Ok, | |
isOk: () => true, | |
isErr: () => false, | |
ok: () => Ok(val), | |
err: () => Err(), | |
unwrap: () => val, | |
unwrapOr: (_) => val, | |
unwrapOrElse: (_) => val, | |
unwrapErr: function () { | |
throw new ReferenceError('Cannot unwrap Err value of Result.Ok') | |
}, | |
match: (matchObject) => matchObject.ok(val), | |
map: (fn) => Ok(fn(val)), | |
mapErr: (_) => Ok(val), | |
andThen: (fn) => fn(val), | |
orElse: (_) => Ok(val), | |
}) | |
const Err = (err) => makeReadOnly({ | |
type: ResultType.Err, | |
isOk: () => false, | |
isErr: () => true, | |
ok: () => Err(), | |
err: () => Err(err), | |
unwrap: function () { | |
throw new ReferenceError('Cannot unwrap Ok value of Result.Err') | |
}, | |
unwrapOr: (_) => _, | |
unwrapOrElse: (fn) => fn(err), | |
unwrapErr: () => err, | |
match: (matchObject) => matchObject.err(err), | |
map: (_) => Err(err), | |
mapErr: (fn) => Err(fn(err)), | |
andThen: (_) => Err(err), | |
orElse: (fn) => fn(err), | |
}) | |
export const Result = makeReadOnly({ | |
ok(value) { | |
return Ok(value); | |
}, | |
fail(error) { | |
return Err(error) | |
}, | |
combine (results) { | |
for (let result of results) if (result.isErr()) return result | |
return Result.ok(); | |
} | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment