Skip to content

Instantly share code, notes, and snippets.

@gordonbrander
Last active February 10, 2020 18:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gordonbrander/dae1b87259331f7ceed192168527bcbd to your computer and use it in GitHub Desktop.
Save gordonbrander/dae1b87259331f7ceed192168527bcbd to your computer and use it in GitHub Desktop.
Racket-style contracts code sketch
// Simple runtime type checking.
export class ContractViolation extends Error {}
export const contract = predicate => value => {
if (predicate(value)) {
return value
} else {
throw new ContractViolation(
`Contract violation. Expected ${predicate}. Given ${value}.`
)
}
}
export const and = (ca, cb) => x => cb(ca(x))
export const or = (ca, cb) => x => {
try {
return ca(x)
} catch (e) {
if (e instanceof ContractViolation) {
return cb(x)
} else {
throw e
}
}
}
export const any = x => x
export const number = contract(x => typeof x === 'number')
export const string = contract(x => typeof x === 'string')
export const nullish = contract(x => x == null)
export const array = contract(Array.isArray)
export const instance = t => contract(x => x instanceof t)
export const length = n => contract(x => x.length === n)
const lambda1 = (ca, cout) => func => a =>
cout(func(ca(a)))
const lambda2 = (ca, cb, cout) => func => (a, b) =>
cout(func(ca(a), cb(b)))
const lambda3 = (ca, cb, cc, cout) => func => (a, b, c) =>
cout(func(ca(a), cb(b), cc(c)))
const lambda4 = (ca, cb, cc, cd, cout) => func => (a, b, c, d) =>
cout(func(ca(a), cb(b), cc(c), cd(d)))
const lambda5 = (ca, cb, cc, cd, ce, cout) => func => (a, b, c, d, e) =>
cout(func(ca(a), cb(b), cc(c), cd(d), ce(e)))
const lambda6 = (ca, cb, cc, cd, ce, cf, cout) => func => (a, b, c, d, e, f) =>
cout(func(ca(a), cb(b), cc(c), cd(d), ce(e), cf(f)))
const lambda7 = (ca, cb, cc, cd, ce, cf, cg, cout) => func =>
(a, b, c, d, e, f, g) =>
cout(func(ca(a), cb(b), cc(c), cd(d), ce(e), cf(f), cg(g)))
const lambda8 = (ca, cb, cc, cd, ce, cf, cg, ch, cout) => func =>
(a, b, c, d, e, f, g, h) =>
cout(func(ca(a), cb(b), cc(c), cd(d), ce(e), cf(f), cg(g), ch(h)))
export const lambda = (...contracts) => {
const nargs = contracts.length - 1
if (nargs === 1) {
return lambda1(...contracts)
} else if (nargs === 2) {
return lambda2(...contracts)
} else if (nargs === 3) {
return lambda3(...contracts)
} else if (nargs === 4) {
return lambda4(...contracts)
} else if (nargs === 5) {
return lambda5(...contracts)
} else if (nargs === 6) {
return lambda6(...contracts)
} else if (nargs === 7) {
return lambda7(...contracts)
} else if (nargs === 8) {
return lambda8(...contracts)
} else {
throw Error(
`Lambda contracts support up to 8 arguments. Given: ${contracts.length}`
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment