feat: Implement subtypes

This should eventually be moved into typed-function itself, but for
  now it can be implemented on top of the existing typed-function.

  Uses subtypes to define (and error-check) gcd and lcm, which are only
  defined for integer arguments.

  Resolves #36.
This commit is contained in:
Glen Whitney 2022-07-30 04:59:04 -07:00
parent 4d38f4161c
commit c429c19dfe
35 changed files with 294 additions and 43 deletions

View file

@ -1,7 +1,10 @@
export * from './Types/generic.mjs'
export {lcm} from './lcm.mjs'
export {mod} from './mod.mjs'
export {multiply} from './multiply.mjs'
export {divide} from './divide.mjs'
export {sign} from './sign.mjs'
export {sqrt} from './sqrt.mjs'
export {square} from './square.mjs'
export {subtract} from './subtract.mjs'

18
src/generic/gcdType.mjs Normal file
View file

@ -0,0 +1,18 @@
/* Returns a object that defines the gcd for the given type */
export default function(type) {
const producer = refs => {
const modder = refs[`mod(${type},${type})`]
const zeroTester = refs[`isZero(${type})`]
return (a,b) => {
while (!zeroTester(b)) {
const r = modder(a,b)
a = b
b = r
}
return a
}
}
const retval = {}
retval[`${type},${type}`] = producer
return retval
}

6
src/generic/lcm.mjs Normal file
View file

@ -0,0 +1,6 @@
export const lcm = {
'any,any': ({
multiply,
quotient,
gcd}) => (a,b) => multiply(quotient(a, gcd(a,b)), b)
}

6
src/generic/mod.mjs Normal file
View file

@ -0,0 +1,6 @@
export const mod = {
'any,any': ({
subtract,
multiply,
quotient}) => (a,m) => subtract(a, multiply(m, quotient(a,m)))
}

View file

@ -4,9 +4,9 @@ export const multiply = {
'undefined': () => u => u,
'undefined,...any': () => (u, rest) => u,
'any,undefined': () => (x, u) => u,
'any,undefined,...any': () => (x, u, rest) => u,
'any,any,undefined': () => (x, y, u) => u,
'any,any,undefined,...any': () => (x, y, u, rest) => u
// Bit of a hack since this should go on indefinitely...
'any,any,...any': ({self}) => (a,b,rest) => {
const later = [b, ...rest]
return later.reduce((x,y) => self(x,y), a)
}
}

3
src/generic/square.mjs Normal file
View file

@ -0,0 +1,3 @@
export const square = {
any: ({multiply}) => x => multiply(x,x)
}