Skip to content

Instantly share code, notes, and snippets.

@madoke
Created March 12, 2023 13:57
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 madoke/d8d8a78ddd2702b755fecca05be3ac93 to your computer and use it in GitHub Desktop.
Save madoke/d8d8a78ddd2702b755fecca05be3ac93 to your computer and use it in GitHub Desktop.
Simple Rules Engine
// The engine
type Rule<T> = (input: T) => boolean;
const All =
<T>(...rules: Rule<T>[]) =>
(input: T) =>
rules.every((r) => r(input));
const Some =
<T>(...rules: Rule<T>[]) =>
(input: T) =>
rules.some((r) => r(input));
const One =
<T>(...rules: Rule<T>[]) =>
(input: T) =>
rules.filter((r) => r(input)).length === 1;
const None =
<T>(...rules: Rule<T>[]) =>
(input: T) =>
rules.filter((r) => r(input)).length === 0;
const ruleRunner =
<T, R>(rules: [R, Rule<T>][]) =>
(input: T) =>
rules.filter(([_, rule]) => rule(input)).map(([output, _]) => output);
// An example
type Ingredient =
| 'salami'
| 'olives'
| 'peppers'
| 'mushrooms'
| 'pineapple'
| 'banana';
type Dough = 'thin' | 'fluffy';
type Source = 'dominos' | 'pizzahut';
type Pizza = {
ingredients: Ingredient[];
dough: Dough;
source: Source;
};
const has = (ingredient: Ingredient) => (pizza: Pizza) =>
pizza.ingredients.includes(ingredient);
const dough = (dough: Dough) => (pizza: Pizza) => pizza.dough === dough;
const source = (source: Source) => (pizza: Pizza) => pizza.source === source;
const rules: [string, Rule<Pizza>][] = [
['Mario', None(has('salami'), has('olives'))],
['Yoshi', All(has('pineapple'), has('banana'), source('dominos'))],
['Luigi', Some(has('mushrooms'), has('peppers'), dough('fluffy'))],
['Princess Peach', One(has('salami'), has('peppers'))]
];
const pizzas: Pizza[] = [
{ ingredients: ['salami'], dough: 'thin', source: 'dominos' },
{ ingredients: ['salami'], dough: 'fluffy', source: 'dominos' },
{ ingredients: ['mushrooms'], dough: 'thin', source: 'pizzahut' },
{ ingredients: ['pineapple'], dough: 'thin', source: 'pizzahut' },
{ ingredients: ['pineapple', 'banana'], dough: 'fluffy', source: 'dominos' },
{ ingredients: ['salami', 'peppers'], dough: 'fluffy', source: 'pizzahut' }
];
for (const pizza of pizzas) {
console.log(ruleRunner(rules)(pizza));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment