Skip to content

Instantly share code, notes, and snippets.

@moatorres
Last active June 27, 2021 13:50
Show Gist options
  • Save moatorres/e742cd698c304a7b0ecf335ee8fa7c9a to your computer and use it in GitHub Desktop.
Save moatorres/e742cd698c304a7b0ecf335ee8fa7c9a to your computer and use it in GitHub Desktop.
Result monad in JS/Node (without classes)
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))
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