const { adt, match } = require("@masaeedu/adt")
// First, we build a language of references and predicates
const ref = adt({
lit: ["some literal value"],
key: ["the name of some field"]
})
const { lit, key } = ref
const predicate = adt({
and: ["predicate", "predicate"],
or: ["predicate", "predicate"],
equals: ["ref", "ref"]
})
const { and, or, equals } = predicate
// Then we construct an expression in this language
// NB: you could also use a parsing library to parse this out of a string
const yourpredicate =
or (equals (key ("key1")) (key ("key2")))
(and (equals (key ("last")) (lit ("Smith")))
(equals (key ("gender")) (lit ("m"))))
console.log(yourpredicate)
// Then we interpret our language into an actual predicate on some value
const resolve = ref.match({
lit: v => _ => v,
key: k => a => a[k]
})
const interpret = predicate.match({
and: f => g => a => interpret(f)(a) && interpret(g)(a),
or: f => g => a => interpret(f)(a) || interpret(g)(a),
equals: r1 => r2 => a => resolve(r1)(a) === resolve(r2)(a)
})
const inputs = [
{ key1: "foo", key2: "bar", last: "Smith", gender: "m" }, // => true
{ key1: "foo", key2: "foo", last: "Hurpenglurper", gender: "m" }, // => true
{ key1: "foo", key2: "bar", last: "Hurpenglurper", gender: "m" } // => false
]
const p = interpret(yourpredicate)
console.log(inputs.map(p))