diff --git a/src/boolean/type.js b/src/boolean/type.js index 169a207..989bd20 100644 --- a/src/boolean/type.js +++ b/src/boolean/type.js @@ -1,14 +1,14 @@ import {BooleanT} from './BooleanT.js' -import {onType} from '#core/helpers.js' +import {match} from '#core/helpers.js' import {Returns, Type, TypeOfTypes, Undefined} from '#core/Type.js' import {NumberT} from '#number/NumberT.js' const bool = f => Returns(BooleanT, f) -export const boolean = onType( - BooleanT, bool(p => p), - NumberT, bool(a => !!a), - TypeOfTypes, bool(() => true), - Undefined, bool(() => false), - [], bool(() => false) -) +export const boolean = [ + match(BooleanT, bool(p => p)), + match(NumberT, bool(a => !!a)), + match(TypeOfTypes, bool(() => true)), + match(Undefined, bool(() => false)), + match([], bool(() => false)) +] diff --git a/src/complex/Complex.js b/src/complex/Complex.js index 7292113..d934fd1 100644 --- a/src/complex/Complex.js +++ b/src/complex/Complex.js @@ -1,5 +1,5 @@ import {Type} from '#core/Type.js' -import {onType} from '#core/helpers.js' +import {match} from '#core/helpers.js' const isComplex = z => z && typeof z === 'object' && 're' in z && 'im' in z @@ -10,15 +10,17 @@ function complexSpecialize(ComponentType) { const specTest = z => isComplex(z) && compTest(z.re) && compTest(z.im) const typeName = `Complex(${ComponentType})` if (ComponentType.concrete) { - const fromSpec = [ - ComponentType, math => r => ({re: r, im: ComponentType.zero})] - for (const [matchType, fctry] of ComponentType.from.patterns) { - fromSpec.push(this.specialize(matchType.type), math => { - const compConv = fctry(math) - return z => ({re: compConv(z.re), im: compConv(z.im)}) - }) + const fromSpec = [match( + ComponentType, math => r => ({re: r, im: ComponentType.zero}))] + for (const {pattern, does} of ComponentType.from) { + fromSpec.push(match( + this.specialize(pattern.type), + math => { + const compConv = does(math) + return z => ({re: compConv(z.re), im: compConv(z.im)}) + })) } - const typeOptions = {from: onType(...fromSpec), typeName} + const typeOptions = {from: fromSpec, typeName} if ('zero' in ComponentType) { typeOptions.zero = {re: ComponentType.zero, im: ComponentType.zero} if ('one' in ComponentType) { diff --git a/src/complex/__test__/Complex.spec.js b/src/complex/__test__/Complex.spec.js index ce232be..9bf8505 100644 --- a/src/complex/__test__/Complex.spec.js +++ b/src/complex/__test__/Complex.spec.js @@ -21,11 +21,11 @@ describe('Complex Type', () => { const convertImps = CplxNum.from let cnvNtoCN let cnvCBtoCN - for (const [pattern, convFactory] of convertImps.patterns) { + for (const {pattern, does} of convertImps) { if (pattern.match([NumberT])[0] === 1) { - cnvNtoCN = convFactory(math) + cnvNtoCN = does(math) } else if (pattern.match([Complex(BooleanT)])[0] === 1) { - cnvCBtoCN = convFactory(math) + cnvCBtoCN = does(math) } } assert.deepStrictEqual(cnvNtoCN(3.5), {re: 3.5, im: 0}) diff --git a/src/complex/type.js b/src/complex/type.js index 68531cb..9881bc5 100644 --- a/src/complex/type.js +++ b/src/complex/type.js @@ -1,10 +1,10 @@ import {Complex} from './Complex.js' -import {onType} from "#core/helpers.js" +import {match} from "#core/helpers.js" import {Returns} from "#core/Type.js" import {Any} from "#core/TypePatterns.js" -export const complex = onType( - Any, (math, T) => { +export const complex = [ + match(Any, (math, T) => { const z = math.zero(T) if (math.hasnan(T)) { const isnan = math.isnan.resolve([T]) @@ -15,8 +15,8 @@ export const complex = onType( }) } return Returns(Complex(T), r => ({re: r, im: z})) - }, - [Any, Any], (math, [T, U]) => { + }), + match([Any, Any], (math, [T, U]) => { if (T !== U) { throw new RangeError( 'mixed complex types disallowed ' @@ -24,5 +24,4 @@ export const complex = onType( } return Returns(Complex(T), (r, m) => ({re: r, im: m})) }) - - +] diff --git a/src/core/Type.js b/src/core/Type.js index 62b048e..868da71 100644 --- a/src/core/Type.js +++ b/src/core/Type.js @@ -21,7 +21,10 @@ export class Type extends Function { }) this.test = f - this.from = options.from ?? {patterns: []} // mock empty Implementations + // we want property `from` to end up as an array of Matchers: + this.from = options.from + ? Array.isArray(options.from) ? options.from : [options.from] + : [] if ('zero' in options) this.zero = options.zero if ('one' in options) this.one = options.one if ('nan' in options) this.nan = options.nan diff --git a/src/core/TypeDispatcher.js b/src/core/TypeDispatcher.js index 6346b6f..903cb5b 100644 --- a/src/core/TypeDispatcher.js +++ b/src/core/TypeDispatcher.js @@ -1,8 +1,8 @@ import ArrayKeyedMap from 'array-keyed-map' import { - Implementations, ImplementationsGenerator, ResolutionError, - isPlainFunction, isPlainObject, onType, types + Implementations, ImplementationsGenerator, Matcher, ResolutionError, + isPlainFunction, isPlainObject, match, types } from './helpers.js' import {bootstrapTypes, Returns, whichType, Type} from './Type.js' import {matched, needsCollection, Passthru} from './TypePatterns.js' @@ -45,11 +45,14 @@ export class TypeDispatcher { // an Implementations that associates it with the Passthru pattern // -- a factory for entities, to be invoked to get the value of a key // for any types. You can just merge that. + // -- a value or behavior that applies just when the types of an + // argument match a type pattern. For that, you merge the result + // of `match(PATTERN, VALUE)` // -- a collection of different values, or different behaviors, or - // different factories for different types for a given key. For that - // you merge an Implementations object that associates each item with - // a TypePattern. An Implementation object can most easily be - // generated with `onType(PATTERN, VALUE, PATTERN, VALUE,...)` + // different factories for different lists of argument types for a + // given key. For that you merge an array of results of `match`, + // so something like + // `[match(PATTERN, VALUE), match(PATTERN, VALUE), ...]` // Initially I thought those were all the possibilities. But then I // wanted to export something that when merged, would set the Passthru // pattern to a fresh specific object for that merge, but so that the @@ -57,10 +60,10 @@ export class TypeDispatcher { // particular TypeDispatcher (this situation applies to the config object). // To produce that behavior, you need a fourth thing // -- an ImplementationGenerator, which is basically a function that - // returns an Implementations object as above. As this is only needed - // for a single entity that will be merged into multiple different - // TypeDispatchers, there's not a big focus on making this convenient; - // it's not expected to come up much. + // returns one of the last couple of options above. As this variant is + // only needed for a single entity that will be merged into multiple + // different TypeDispatchers, there's not a big focus on making + // specifying it convenient; it's not expected to come up much. merge(spec) { if (!spec) return @@ -74,9 +77,7 @@ export class TypeDispatcher { // For special cases like types, config, etc, we can wrap // a function in ImplementationsGenerator to produce the thing // we should really merge: - if (val instanceof ImplementationsGenerator) { - val = val.generate() - } + if (val instanceof ImplementationsGenerator) val = val.generate() // Now dispatch on what sort of thing we are supposed to merge: if (val instanceof Type) { @@ -100,7 +101,14 @@ export class TypeDispatcher { // Everything else we coerce into Implementations and deal with // right here: - if (!(val instanceof Implementations)) val = onType(Passthru, val) + if (val instanceof Matcher) val = new Implementations(val) + if (Array.isArray(val)) val = new Implementations(val) + if (!(val instanceof Implementations)) { + val = new Implementations(match(Passthru, val)) + } + + // hereafter we may assume that val is an instance of Implementations + if (!(key in this)) { // Need to "bootstrap" the item: // We initially define it with a temporary getter, only @@ -189,11 +197,11 @@ export class TypeDispatcher { this._behaviors[key] = new ArrayKeyedMap() } - // Now add all of the patterns of this implementation: - for (const [pattern, result] of val.patterns) { + // Now add all of the matchers of this Implementations: + for (const {pattern, does} of val.matchers) { if (pattern === Passthru) { if (key in this._fallbacks) this._disengageFallback(key) - this._fallbacks[key] = result + this._fallbacks[key] = does } else { this._clearBehaviorsMatching(key, pattern) // if it happens the same pattern is already in the @@ -201,7 +209,7 @@ export class TypeDispatcher { const imps = this._implementations[key] const have = imps.findIndex(elt => pattern.equal(elt[0])) if (have >= 0) imps.splice(have, 1) - this._implementations[key].unshift([pattern, result]) + this._implementations[key].unshift([pattern, does]) } } } diff --git a/src/core/TypePatterns.js b/src/core/TypePatterns.js index a2e877f..eb73afd 100644 --- a/src/core/TypePatterns.js +++ b/src/core/TypePatterns.js @@ -21,7 +21,7 @@ class MatchTypePattern extends TypePattern { if (position < typeSequence.length) { if (this.type.specializesTo(actual)) return [position + 1, actual] if (options.convert) { - for (const [pattern, convertor] of this.type.from.patterns) { + for (const {pattern, does: convertor} of this.type.from) { const [pos] = pattern.match([actual]) if (pos === 1) { return [position + 1, {actual, convertor, matched: this.type}] diff --git a/src/core/__test__/TypeDispatcher.spec.js b/src/core/__test__/TypeDispatcher.spec.js index a5fdac8..37e5618 100644 --- a/src/core/__test__/TypeDispatcher.spec.js +++ b/src/core/__test__/TypeDispatcher.spec.js @@ -4,7 +4,7 @@ import * as booleans from '#boolean/all.js' import * as generics from '#generic/all.js' import * as numbers from '#number/all.js' import {NumberT} from '#number/NumberT.js' -import {onType, ResolutionError} from "#core/helpers.js" +import {match, ResolutionError} from "#core/helpers.js" import {Any} from "#core/TypePatterns.js" import {Returns, NotAType} from "#core/Type.js" import {plain} from "#number/helpers.js" @@ -20,10 +20,10 @@ describe('TypeDispatcher', () => { assert.strictEqual(incremental.add(-1.5, 0.5), -1) assert.throws(() => incremental.add(7, undefined), ResolutionError) // Make Undefined act like zero: - incremental.merge({add: onType( - [Undefined, Any], (_m, [_U, T]) => Returns(T, (_a, b) => b), - [Any, Undefined], (_m, [T]) => Returns(T, a => a) - )}) + incremental.merge({add: [ + match([Undefined, Any], (_m, [_U, T]) => Returns(T, (_a, b) => b)), + match([Any, Undefined], (_m, [T]) => Returns(T, a => a)) + ]}) assert.strictEqual(incremental.add(7, undefined), 7) assert.strictEqual( incremental.resolve('add', [TypeOfTypes, Undefined]).returns, @@ -34,10 +34,10 @@ describe('TypeDispatcher', () => { NumberT) // Oops, changed my mind ;-), make it work like NaN with numbers: const alwaysNaN = Returns(NumberT, () => NaN) - incremental.merge({add: onType( - [Undefined, NumberT], alwaysNaN, - [NumberT, Undefined], alwaysNaN - )}) + incremental.merge({add: [ + match([Undefined, NumberT], alwaysNaN), + match([NumberT, Undefined], alwaysNaN) + ]}) assert(isNaN(incremental.add(undefined, -3.25))) assert.strictEqual( incremental.add.resolve([Undefined, NumberT]).returns, @@ -61,7 +61,7 @@ describe('TypeDispatcher', () => { assert.strictEqual(bgn.negate(true), -1) assert(bgn._behaviors.negate.has([BooleanT])) const deps = bgn._dependencies.negate - bgn.merge({number: onType([BooleanT], Returns(NumberT, b => b ? 2 : 0))}) + bgn.merge({number: match([BooleanT], Returns(NumberT, b => b ? 2 : 0))}) assert(!bgn._behaviors.negate.has([BooleanT])) assert.strictEqual(bgn.negate(true), -2) }) diff --git a/src/core/__test__/helpers.spec.js b/src/core/__test__/helpers.spec.js index c8321d8..10849d6 100644 --- a/src/core/__test__/helpers.spec.js +++ b/src/core/__test__/helpers.spec.js @@ -1,16 +1,15 @@ import assert from 'assert' import { - Implementations, onType, isPlainObject, isPlainFunction + Matcher, match, isPlainObject, isPlainFunction, Implementations } from '../helpers.js' import {Type, Undefined, TypeOfTypes} from '../Type.js' import {TypePattern} from '../TypePatterns.js' describe('Core helpers', () => { - it('defines what Implementations are', () => { - const imps = onType(Undefined, 7, [TypeOfTypes, Undefined], -3) - assert(imps instanceof Implementations) - assert(imps.patterns instanceof Array) - assert(imps.patterns.every(([k]) => k instanceof TypePattern)) + it('defines what Matchers are', () => { + const matcher = match([TypeOfTypes, Undefined], -3) + assert(matcher instanceof Matcher) + assert(matcher.pattern instanceof TypePattern) }) it('detects plain objects', () => { diff --git a/src/core/helpers.js b/src/core/helpers.js index f741859..dc05182 100644 --- a/src/core/helpers.js +++ b/src/core/helpers.js @@ -1,21 +1,21 @@ import {pattern, Passthru} from './TypePatterns.js' -export class Implementations { - constructor(imps) { - this.patterns = [] - this._add(imps) - } - _add(imps) { - for (let i = 0; i < imps.length; ++i) { - this.patterns.push([pattern(imps[i]), imps[++i]]) - } - } - also(...imps) { - this._add(imps) +export class Matcher { + constructor(spec, facOrBehave) { + this.pattern = pattern(spec) + this.does = facOrBehave } } -export const onType = (...imps) => new Implementations(imps) +export class Implementations { + constructor(impOrImps) { + if (Array.isArray(impOrImps)) { + this.matchers = impOrImps + } else this.matchers = [impOrImps] + } +} + +export const match = (spec, facOrBehave) => new Matcher(spec, facOrBehave) export class ImplementationsGenerator { constructor(f) { @@ -34,7 +34,7 @@ export class ImplementationsGenerator { // collection of types (and modifying the types in one would affect them // all). Hence we do: -export const types = new ImplementationsGenerator(() => onType(Passthru, {})) +export const types = new ImplementationsGenerator(() => match(Passthru, {})) export class ResolutionError extends TypeError { constructor(...args) { diff --git a/src/coretypes/relational.js b/src/coretypes/relational.js index 3d5712f..4192dc1 100644 --- a/src/coretypes/relational.js +++ b/src/coretypes/relational.js @@ -1,8 +1,8 @@ -import {onType} from '#core/helpers.js' +import {match} from '#core/helpers.js' import {TypeOfTypes, Undefined} from '#core/Type.js' import {boolnum} from '#number/helpers.js' -export const indistinguishable = onType( - [Undefined, Undefined], boolnum(() => true), - [TypeOfTypes, TypeOfTypes], boolnum((t, u) => t === u) -) +export const indistinguishable = [ + match([Undefined, Undefined], boolnum(() => true)), + match([TypeOfTypes, TypeOfTypes], boolnum((t, u) => t === u)) +] diff --git a/src/coretypes/utils.js b/src/coretypes/utils.js index dcea51a..4386ac1 100644 --- a/src/coretypes/utils.js +++ b/src/coretypes/utils.js @@ -1,47 +1,47 @@ -import {onType} from '#core/helpers.js' +import {match} from '#core/helpers.js' import {NotAType, Returns, TypeOfTypes} from '#core/Type.js' import {Any} from "#core/TypePatterns.js" import {boolnum} from "#number/helpers.js" -export const zero = onType( - Any, (math, T) => { +export const zero = [ + match(Any, (math, T) => { const z = math.zero(T) return Returns(T, () => z) - }, - TypeOfTypes, Returns(NotAType, t => { + }), + match(TypeOfTypes, Returns(NotAType, t => { if ('zero' in t) return t.zero throw new RangeError(`type '${t}' has no zero element`) - }) -) + })) +] -export const one = onType( - Any, (math, T) => { +export const one = [ + match(Any, (math, T) => { const unit = math.one(T) return Returns(T, () => unit) - }, - TypeOfTypes, Returns(NotAType, t => { + }), + match(TypeOfTypes, Returns(NotAType, t => { if ('one' in t) return t.one throw new RangeError( `type '${t}' has no unit element designated as "one"`) - }) -) + })) +] -export const hasnan = onType( - Any, (math, T) => { +export const hasnan = [ + match(Any, (math, T) => { const answer = math.hasnan(T) return Returns(math.typeOf(answer), () => answer) - }, - TypeOfTypes, boolnum(t => 'nan' in t) -) + }), + match(TypeOfTypes, boolnum(t => 'nan' in t)) +] -export const nan = onType( - Any, (math, T) => { +export const nan = [ + match(Any, (math, T) => { const notanum = math.nan(T) return Returns(T, () => notanum) - }, - TypeOfTypes, Returns(NotAType, t => { + }), + match(TypeOfTypes, Returns(NotAType, t => { if ('nan' in t) return t.nan throw new RangeError( `type '${t}' has no "not a number" element`) - }) -) + })) +] diff --git a/src/generic/arithmetic.js b/src/generic/arithmetic.js index 433f373..fe1556f 100644 --- a/src/generic/arithmetic.js +++ b/src/generic/arithmetic.js @@ -1,8 +1,8 @@ -import {onType} from '#core/helpers.js' +import {match} from '#core/helpers.js' import {Returns} from '#core/Type.js' import {Any} from '#core/TypePatterns.js' -export const square = onType(Any, (math, T) => { +export const square = match(Any, (math, T) => { const mult = math.multiply.resolve([T, T]) return Returns(mult.returns, a => mult(a, a)) }) diff --git a/src/generic/config.js b/src/generic/config.js index 134d717..9f421ec 100644 --- a/src/generic/config.js +++ b/src/generic/config.js @@ -1,5 +1,5 @@ -import {ImplementationsGenerator, onType} from '#core/helpers.js' +import {ImplementationsGenerator, match} from '#core/helpers.js' import {Passthru} from '#core/TypePatterns.js' export const config = new ImplementationsGenerator( - () => onType(Passthru, {relTol: 1e-12, absTol: 1e-15})) + () => match(Passthru, {relTol: 1e-12, absTol: 1e-15})) diff --git a/src/generic/relational.js b/src/generic/relational.js index de5b95b..9022777 100644 --- a/src/generic/relational.js +++ b/src/generic/relational.js @@ -1,10 +1,10 @@ import {ReturnsAs} from './helpers.js' -import {onType} from '#core/helpers.js' +import {match} from '#core/helpers.js' import {Returns} from '#core/Type.js' import {Any, matched} from '#core/TypePatterns.js' import {boolnum} from '#number/helpers.js' -export const equal = onType([Any, Any], (math, [T, U]) => { +export const equal = match([Any, Any], (math, [T, U]) => { // Finding the correct signature of `indistinguishable` to use for // testing (approximate) equality is tricky, because T or U might // need to be converted for the sake of comparison, and some types @@ -38,7 +38,7 @@ export const equal = onType([Any, Any], (math, [T, U]) => { // now that we have `equal` and `exceeds`, pretty much everything else should // be easy: -export const compare = onType([Any, Any], (math, [T, U]) => { +export const compare = match([Any, Any], (math, [T, U]) => { const eq = math.equal.resolve([T, U]) const gt = math.exceeds.resolve([T, U]) const zero = math.zero(T) // asymmetry here is unfortunate, but we have @@ -70,7 +70,7 @@ export const compare = onType([Any, Any], (math, [T, U]) => { }) }) -export const sign = onType(Any, (math, T) => { +export const sign = match(Any, (math, T) => { const zero = math.zero(T) const comp = math.compare.resolve([T, T]) return ReturnsAs(comp, t => comp(t, zero)) @@ -81,25 +81,25 @@ export const unequal = (math, types) => { return ReturnsAs(eq, (...args) => !eq(...args)) } -export const larger = onType([Any, Any], (math, [T, U]) => { +export const larger = match([Any, Any], (math, [T, U]) => { const eq = math.equal.resolve([T, U]) const bigger = math.exceeds.resolve([T, U]) return boolnum((t, u) => !eq(t, u) && bigger(t, u))(math) }) -export const largerEq = onType([Any, Any], (math, [T, U]) => { +export const largerEq = match([Any, Any], (math, [T, U]) => { const eq = math.equal.resolve([T, U]) const bigger = math.exceeds.resolve([T, U]) return ReturnsAs(bigger, (t, u) => eq(t, u) || bigger(t, u)) }) -export const smaller = onType([Any, Any], (math, [T, U]) => { +export const smaller = match([Any, Any], (math, [T, U]) => { const eq = math.equal.resolve([T, U]) const bigger = math.exceeds.resolve([U, T]) return boolnum((t, u) => !eq(t, u) && bigger(u, t))(math) }) -export const smallerEq = onType([Any, Any], (math, [T, U]) => { +export const smallerEq = match([Any, Any], (math, [T, U]) => { const eq = math.equal.resolve([T, U]) const bigger = math.exceeds.resolve([U, T]) return ReturnsAs(bigger, (t, u) => eq(t, u) || bigger(u, t)) diff --git a/src/generic/utils.js b/src/generic/utils.js index 29d9150..8fc8a82 100644 --- a/src/generic/utils.js +++ b/src/generic/utils.js @@ -1,5 +1,5 @@ import {ReturnsAs} from './helpers.js' -import {onType, ResolutionError} from '#core/helpers.js' +import {ResolutionError} from '#core/helpers.js' import {Returns} from '#core/Type.js' import {Any} from "#core/TypePatterns.js" diff --git a/src/number/NumberT.js b/src/number/NumberT.js index 220c28e..c3816a0 100644 --- a/src/number/NumberT.js +++ b/src/number/NumberT.js @@ -1,9 +1,9 @@ import {Type} from '#core/Type.js' -import {onType} from '#core/helpers.js' +import {match} from '#core/helpers.js' import {BooleanT} from '#boolean/BooleanT.js' export const NumberT = new Type(n => typeof n === 'number', { - from: onType(BooleanT, math => math.number.resolve([BooleanT])), + from: match(BooleanT, math => math.number.resolve([BooleanT])), one: 1, zero: 0, nan: NaN diff --git a/src/number/__test__/NumberT.spec.js b/src/number/__test__/NumberT.spec.js index b028025..5254d06 100644 --- a/src/number/__test__/NumberT.spec.js +++ b/src/number/__test__/NumberT.spec.js @@ -14,9 +14,9 @@ describe('NumberT Type', () => { it('can convert from BooleanT to NumberT', () => { const convertImps = NumberT.from let cnvBtoN - for (const [pattern, convFactory] of convertImps.patterns) { + for (const {pattern, does} of convertImps) { if (pattern.match([BooleanT])[0] === 1) { - cnvBtoN = convFactory(math) + cnvBtoN = does(math) break } } diff --git a/src/number/helpers.js b/src/number/helpers.js index 828927c..4ab75af 100644 --- a/src/number/helpers.js +++ b/src/number/helpers.js @@ -1,9 +1,9 @@ import {NumberT} from './NumberT.js' -import {onType} from '#core/helpers.js' +import {match} from '#core/helpers.js' import {Returns} from '#core/Type.js' -export const plain = f => onType( +export const plain = f => match( Array(f.length).fill(NumberT), Returns(NumberT, f)) // Takes a behavior returning boolean, and returns a factory diff --git a/src/number/relational.js b/src/number/relational.js index 87a8152..8839c37 100644 --- a/src/number/relational.js +++ b/src/number/relational.js @@ -1,4 +1,4 @@ -import {onType} from '#core/helpers.js' +import {match} from '#core/helpers.js' import {Returns} from '#core/Type.js' import {Optional} from '#core/TypePatterns.js' import {boolnum} from './helpers.js' @@ -11,7 +11,7 @@ import {NumberT} from './NumberT.js' // Notice a feature of TypedDispatcher: if you specify one tolerance, you must // specify both. -export const indistinguishable = onType( +export const indistinguishable = match( [NumberT, NumberT, Optional([NumberT, NumberT])], boolnum((a, b, [tolerances = [0, 0]]) => { const [relTol, absTol] = tolerances @@ -34,4 +34,4 @@ export const indistinguishable = onType( // Returns truthy if a (interpreted as completely precise) represents a // greater value than b (interpreted as completely precise). Note that even if // so, a and b might be indistinguishable() to some tolerances. -export const exceeds = onType([NumberT, NumberT], boolnum((a, b) => a > b)) +export const exceeds = match([NumberT, NumberT], boolnum((a, b) => a > b)) diff --git a/src/number/type.js b/src/number/type.js index 9ec8fed..ddb47cc 100644 --- a/src/number/type.js +++ b/src/number/type.js @@ -1,13 +1,14 @@ import {plain} from './helpers.js' import {BooleanT} from '#boolean/BooleanT.js' +import {match} from '#core/helpers.js' import {Returns} from '#core/Type.js' import {NumberT} from '#number/NumberT.js' const num = f => Returns(NumberT, f) -export const number = plain(a => a) -number.also( +export const number = [ + plain(a => a), // conversions from Boolean should be consistent with one and zero: - BooleanT, num(p => p ? NumberT.one : NumberT.zero), - [], num(() => 0) -) + match(BooleanT, num(p => p ? NumberT.one : NumberT.zero)), + match([], num(() => 0)) +] diff --git a/src/number/utils.js b/src/number/utils.js index 87da6d9..08372c4 100644 --- a/src/number/utils.js +++ b/src/number/utils.js @@ -2,7 +2,7 @@ import {plain, boolnum} from './helpers.js' import {NumberT} from './NumberT.js' import {Returns} from '#core/Type.js' -import {onType} from '#core/helpers.js' +import {match} from '#core/helpers.js' export const clone = plain(a => a) -export const isnan = onType(NumberT, boolnum(isNaN)) +export const isnan = match(NumberT, boolnum(isNaN))