Skip to content

Instantly share code, notes, and snippets.

@madoke
Created March 12, 2023 13:57
Show Gist options
  • Save madoke/d8d8a78ddd2702b755fecca05be3ac93 to your computer and use it in GitHub Desktop.
Save madoke/d8d8a78ddd2702b755fecca05be3ac93 to your computer and use it in GitHub Desktop.

Revisions

  1. madoke created this gist Mar 12, 2023.
    70 changes: 70 additions & 0 deletions simplerules.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,70 @@
    // 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));
    }