Combinator-Based Architecture
What is Combinator-Based Architecture?
Combinator-based architecture means the entire language is built from simple, composable functions called combinators. There are no classes, no inheritance, no methods - everything is function composition.
/* Everything is built from combinators */
/* map, filter, reduce, compose, pipe, each, via */
/* No classes, no inheritance, no methods */
Why is This Esoteric?
Most programming languages are built around objects, classes, and methods. Our language is built entirely around function composition and combinators - a completely different paradigm.
Core Combinators
map
- Transform Elements
/* map applies a function to every element in a collection */
double : x -> x * 2;
numbers : {1, 2, 3, 4, 5};
doubled : map @double numbers; /* {2, 4, 6, 8, 10} */
/* map works with any function */
increment : x -> x + 1;
incremented : map @increment numbers; /* {2, 3, 4, 5, 6} */
filter
- Select Elements
/* filter keeps elements that satisfy a condition */
is_even : x -> x % 2 = 0;
numbers : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
evens : filter @is_even numbers; /* {2, 4, 6, 8, 10} */
/* filter with custom conditions */
is_greater_than_five : x -> x > 5;
large_numbers : filter @is_greater_than_five numbers; /* {6, 7, 8, 9, 10} */
reduce
- Accumulate Elements
/* reduce combines all elements into a single value */
numbers : {1, 2, 3, 4, 5};
sum : reduce @add 0 numbers; /* 15 */
product : reduce @multiply 1 numbers; /* 120 */
/* reduce with custom accumulation */
max_value : reduce @max 0 numbers; /* 5 */
min_value : reduce @min 1000 numbers; /* 1 */
each
- Multi-Argument Operations
/* each applies a function to corresponding elements from multiple collections */
numbers1 : {1, 2, 3, 4, 5};
numbers2 : {10, 20, 30, 40, 50};
/* Element-wise addition */
sums : each @add numbers1 numbers2; /* {11, 22, 33, 44, 55} */
/* Element-wise multiplication */
products : each @multiply numbers1 numbers2; /* {10, 40, 90, 160, 250} */
Function Composition Combinators
compose
- Mathematical Composition
/* compose(f, g)(x) = f(g(x)) */
double : x -> x * 2;
increment : x -> x + 1;
square : x -> x * x;
/* Compose functions */
double_then_increment : compose @increment @double;
increment_then_square : compose @square @increment;
/* Use composed functions */
result1 : double_then_increment 5; /* double(5)=10, increment(10)=11 */
result2 : increment_then_square 5; /* increment(5)=6, square(6)=36 */
pipe
- Pipeline Composition
/* pipe(f, g)(x) = g(f(x)) - left to right */
double_then_square : pipe @double @square;
result : double_then_square 5; /* double(5)=10, square(10)=100 */
via
- Natural Composition
/* via provides natural composition syntax */
complex_transform : double via increment via square;
result : complex_transform 3; /* square(3)=9, increment(9)=10, double(10)=20 */
Building Complex Operations
Data Processing Pipeline
/* Build complex operations from simple combinators */
data : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
/* Pipeline: filter → map → reduce */
is_even : x -> x % 2 = 0;
double : x -> x * 2;
sum : x -> reduce @add 0 x;
/* Combine combinators */
pipeline : sum via map @double via filter @is_even;
result : pipeline data; /* 60 */
/* Step by step:
1. filter @is_even data → {2, 4, 6, 8, 10}
2. map @double {2, 4, 6, 8, 10} → {4, 8, 12, 16, 20}
3. sum {4, 8, 12, 16, 20} → 60
*/
Validation Chain
/* Build validation from combinators */
validate_positive : x -> x > 0;
validate_even : x -> x % 2 = 0;
validate_small : x -> x < 10;
/* Chain validations */
all_validations : validate_small via validate_even via validate_positive;
result : all_validations 6; /* true (6 > 0, 6 % 2 = 0, 6 < 10) */
Table-Specific Combinators
The t.
namespace provides table-specific combinators:
/* Table operations as combinators */
data : {a: 1, b: 2, c: 3};
/* Get keys and values */
keys : t.keys data; /* {"a", "b", "c"} */
values : t.values data; /* {1, 2, 3} */
/* Check and get values */
has_a : t.has data "a"; /* true */
value_a : t.get data "a"; /* 1 */
/* Transform tables */
with_d : t.set data "d" 4; /* {a: 1, b: 2, c: 3, d: 4} */
without_b : t.delete data "b"; /* {a: 1, c: 3} */
/* Merge tables */
table1 : {a: 1, b: 2};
table2 : {c: 3, d: 4};
merged : t.merge table1 table2; /* {a: 1, b: 2, c: 3, d: 4} */
Advanced Combinator Patterns
Function Factories
/* Create combinators that generate other combinators */
create_multiplier : factor -> multiply factor;
double : create_multiplier 2;
triple : create_multiplier 3;
/* Use generated combinators */
numbers : {1, 2, 3, 4, 5};
doubled : map @double numbers; /* {2, 4, 6, 8, 10} */
tripled : map @triple numbers; /* {3, 6, 9, 12, 15} */
Conditional Combinators
/* Combinators that choose based on conditions */
conditional_map : condition transform_false transform_true ->
when condition is
true then transform_true
_ then transform_false;
/* Use conditional combinator */
is_positive : x -> x > 0;
double : x -> x * 2;
square : x -> x * x;
conditional_transform : conditional_map is_positive @square @double;
result : map conditional_transform {1, -2, 3, -4, 5};
/* Result: {1, -4, 9, -8, 25} (positive numbers squared, negative doubled) */
Recursive Combinators
/* Combinators that can be applied recursively */
repeat_transform : n transform ->
when n is
0 then identity
_ then compose transform (repeat_transform (n - 1) transform);
/* Use recursive combinator */
double : x -> x * 2;
double_three_times : repeat_transform 3 @double;
result : double_three_times 5; /* 40 (5 * 2 * 2 * 2) */
When to Use Combinators
Use combinators when:
- Processing collections of data
- Building data transformation pipelines
- Creating reusable function components
- Working with functional programming patterns
- Building complex operations from simple ones
Don't use combinators when:
- You need side effects (combinators are pure)
- You need complex object-oriented patterns
- You're working with simple, one-off operations
- You need imperative control flow
Common Patterns
/* Pattern 1: Data transformation pipeline */
data : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
/* Build pipeline from combinators */
pipeline : sum via map @double via filter @is_even;
result : pipeline data; /* 60 */
/* Pattern 2: Validation pipeline */
validate_user : user ->
all_validations : validate_email via validate_age via validate_name;
all_validations user;
/* Pattern 3: Configuration builder */
build_config : base_config overrides ->
t.merge base_config overrides;
Key Takeaways
- Function composition - everything is built from function composition
- No objects - no classes, inheritance, or methods
- Composable - combinators can be combined into complex operations
- Pure functions - no side effects, predictable behavior
- Mathematical thinking - operations are mathematical transformations
Why This Matters
Combinator-based architecture makes the language fundamentally different:
- Mathematical foundation - based on function theory and category theory
- Composability - complex operations built from simple, reusable parts
- Predictability - pure functions with no side effects
- Functional thinking - encourages thinking in terms of transformations
- No state management - no mutable state to manage
This architecture makes the language feel more like mathematical notation than traditional programming! 🚀