function* explainInvalid(values, predicates, via) { if (values.length !== predicates.length) return; const pairs = _.zip(predicates, values); const isInvalid = _.negate(_.spread(isValid)); const index = _.findIndex(pairs, isInvalid); if (index !== -1) { const [spec, val] = pairs[index]; yield* firstProblem(spec, val, {path: [index], via, _in: [index]}); } }
function tuple(...predicates) { return { conform: values => (values.length === predicates.length && _.every(_.zip(predicates, values), _.spread(isValid))) ? values : invalidString, unform: _.identity, gen: () => tcg.array(_.map(predicates, gen)), describe: () => [tuple.name, ...describe(predicates)], explain: function*(values, {via}) { yield* explainPredicate(values, predicates, {via}); yield* explainInvalid(values, predicates, via); } }; }