Pattern Matching Skill
SkillDev toolsExpert skill for implementing pattern matching including exhaustiveness checking, decision tree compilation, and efficient match dispatch code generation.
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; ahel provides instructions and does not run this skill.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the Pattern Matching Skill skill
What this skill tells your AI
The instructions your AI receives, as published by a5c-ai/babysitter in library/specializations/programming-languages/skills/pattern-matching/SKILL.md and read by ahel’s review.
Implement pattern matching for programming languages including exhaustiveness checking, usefulness analysis, and efficient compilation to decision trees.
Capabilities
- Parse pattern syntax (constructor, wildcard, binding, literals)
- Implement exhaustiveness and usefulness checking
- Compile patterns to decision trees
- Implement guard clause handling
- Design or-patterns and as-patterns
- Implement nested pattern matching
- Optimize pattern match coverage
- Generate efficient match dispatch code
Usage
Invoke this skill when you need to:
- Add pattern matching to a language
- Implement exhaustiveness checking
- Compile patterns efficiently
- Handle complex pattern features
Inputs
| Parameter | Type | Required | Description |
|---|---|---|---|
| patternTypes | array | Yes | Types of patterns to support |
| targetLanguage | string | Yes | Language for implementation |
| compilationStrategy | string | No | Strategy (decision-tree, backtracking) |
| features | array | No | Advanced features to implement |
Pattern Types
{
"patternTypes": [
"wildcard",
"variable",
"literal",
"constructor",
"tuple",
"record",
"list",
"or-pattern",
"as-pattern",
"guard"
]
}
Feature Options
{
"features": [
"exhaustiveness-checking",
"usefulness-checking",
"decision-tree-compilation",
"guard-clauses",
"nested-patterns",
"view-patterns",
"active-patterns"
]
}
Output Structure
pattern-matching/
├── syntax/
│ ├── pattern.grammar # Pattern syntax
│ └── match-expr.grammar # Match expression syntax
├── analysis/
│ ├── exhaustiveness.ts # Exhaustiveness checker
│ ├── usefulness.ts # Usefulness/redundancy checker
│ └── pattern-types.ts # Pattern type inference
├── compilation/
│ ├── decision-tree.ts # Decision tree builder
│ ├── code-generator.ts # Code generation
│ └── optimizer.ts # Pattern optimization
├── runtime/
│ ├── matcher.ts # Runtime matching (interpreter)
│ └── guards.ts # Guard evaluation
└── tests/
├── exhaustiveness.test.ts
├── compilation.test.ts
└── runtime.test.ts
Pattern Syntax
// Pattern ADT
type Pattern =
| { type: 'wildcard' } // _
| { type: 'variable'; name: string } // x
| { type: 'literal'; value: Literal } // 42, "hello", true
| { type: 'constructor'; name: string; args: Pattern[] } // Some(x), Cons(h, t)
| { type: 'tuple'; elements: Pattern[] } // (x, y, z)
| { type: 'record'; fields: Map<string, Pattern> } // { name: n, age: a }
| { type: 'list'; elements: Pattern[]; rest?: Pattern } // [x, y, ...rest]
| { type: 'or'; patterns: Pattern[] } // p1 | p2
| { type: 'as'; pattern: Pattern; name: string } // p as x
| { type: 'guard'; pattern: Pattern; guard: Expr }; // p if cond
// Match expression
interface MatchExpr {
scrutinee: Expr;
arms: MatchArm[];
}
interface MatchArm {
pattern: Pattern;
guard?: Expr;
body: Expr;
}
Exhaustiveness Checking
// Based on "Warnings for Pattern Matching" (Maranget)
type PatternMatrix = Pattern[][]; // rows = arms, columns = scrutinees
// Check if pattern matrix is exhaustive
function isExhaustive(matrix: PatternMatrix, types: Type[]): boolean {
if (matrix.length === 0) return false;
if (types.length === 0) return true;
const firstCol = matrix.map(row => row[0]);
const sigma = getConstructorSignature(types[0]);
if (sigma.isComplete(firstCol)) {
// All constructors present - check specializations
return sigma.constructors.every(ctor =>
isExhaustive(specialize(matrix, ctor), specializationTypes(types, ctor))
);
} else {
// Some constructors missing - check default matrix
return isExhaustive(defaultMatrix(matrix), types.slice(1));
}
}
// Generate witness for non-exhaustiveness
function findUncoveredCase(matrix: PatternMatrix, types: Type[]): Pattern[] | null {
if (matrix.length === 0) {
// Empty matrix - any value is uncovered
return types.map(generateWildcard);
}
if (types.length === 0) return null; // Exhaustive
const sigma = getConstructorSignature(types[0]);
const firstCol = matrix.map(row => row[0]);
if (sigma.isComplete(firstCol)) {
for (const ctor of sigma.constructors) {
const witness = findUncoveredCase(
specialize(matrix, ctor),
specializationTypes(types, ctor)
);
if (witness) {
return [applyConstructor(ctor, witness.slice(0, ctor.arity)), ...witness.slice(ctor.arity)];
}
}
return null;
} else {
// Find missing constructor
const missing = sigma.constructors.find(c => !firstCol.some(p => matchesCtor(p, c)));
if (missing) {
return [generatePattern(missing), ...types.slice(1).map(generateWildcard)];
}
return findUncoveredCase(defaultMatrix(matrix), types.slice(1));
}
}
Decision Tree Compilation
// Decision tree for efficient matching
type DecisionTree =
| { type: 'fail' }
| { type: 'leaf'; bindings: Map<string, Access>; body: Expr }
| { type: 'switch'; access: Access; cases: SwitchCase[]; default?: DecisionTree };
interface SwitchCase {
constructor: Constructor;
tree: DecisionTree;
}
interface Access {
root: string;
path: AccessStep[];
}
type AccessStep =
| { type: 'field'; index: number }
| { type: 'deref' };
// Compile patterns to decision tree
function compilePatterns(arms: MatchArm[], scrutinee: Access): DecisionTree {
if (arms.length === 0) return { type: 'fail' };
// Find best column to split on (heuristic)
const column = selectColumn(arms);
// Group arms by constructor in that column
const groups = groupByConstructor(arms, column);
if (groups.size === 0) {
// All wildcards - just use first arm
const bindings = extractBindings(arms[0].pattern, scrutinee);
return { type: 'leaf', bindings, body: arms[0].body };
}
// Build switch node
const cases: SwitchCase[] = [];
for (const [ctor, ctorArms] of groups) {
const specializedAccess = extendAccess(scrutinee, ctor);
cases.push({
constructor: ctor,
tree: compilePatterns(specializeArms(ctorArms, ctor), specializedAccess)
});
}
const defaultArms = arms.filter(arm => isWildcard(arm.pattern, column));
const defaultTree = defaultArms.length > 0
? compilePatterns(defaultArms, scrutinee)
: undefined;
return { type: 'switch', access: scrutinee, cases, default: defaultTree };
}
Guard Clause Handling
// Guards complicate exhaustiveness - we must be conservative
interface GuardedArm {
pattern: Pattern;
guard: Expr | null;
body: Expr;
}
// For exhaustiveness: treat guarded patterns as potentially failing
function exhaustivenessWithGuards(arms: GuardedArm[], types: Type[]): Warning[] {
const warnings: Warning[] = [];
// Remove guards for exhaustiveness check (conservative)
const unguardedMatrix = arms.map(arm => [arm.pattern]);
if (!isExhaustive(unguardedMatrix, types)) {
// May still be exhaustive if guards cover all cases
// But we can't know statically - warn
warnings.push({
type: 'possibly-non-exhaustive',
message: 'Match may not be exhaustive (guards present)',
suggestion: 'Consider adding a catch-all pattern'
});
}
return warnings;
}
// Decision tree with guards
type GuardedTree =
| { type: 'fail' }
| { type: 'guard'; test: Expr; success: GuardedTree; failure: GuardedTree }
| { type: 'leaf'; bindings: Map<string, Access>; body: Expr }
| { type: 'switch'; access: Access; cases: SwitchCase[]; default?: GuardedTree };
Code Generation
// Generate code from decision tree
function generateCode(tree: DecisionTree, target: CodeTarget): Code {
switch (tree.type) {
case 'fail':
return target.emitMatchFailure();
case 'leaf':
const setup = Array.from(tree.bindings.entries())
.map(([name, access]) => target.emitBinding(name, access));
return target.emitBlock([...setup, target.emitExpr(tree.body)]);
case 'switch':
return target.emitSwitch(
target.emitAccess(tree.access),
tree.cases.map(c => ({
test: target.emitConstructorTest(c.constructor),
body: generateCode(c.tree, target)
})),
tree.default ? generateCode(tree.default, target) : target.emitMatchFailure()
);
}
}
// Example output for Rust
function emitRustMatch(tree: DecisionTree): string {
// Input: match x { Some(y) => y + 1, None => 0 }
// Output:
// match x {
// Some(ref __0) => {
// let y = __0;
// y + 1
// }
// None => 0
// }
}
Or-Patterns and As-Patterns
// Or-pattern: matches if any sub-pattern matches
// (Red | Green | Blue) => "color"
function expandOrPattern(pattern: Pattern): Pattern[] {
if (pattern.type === 'or') {
return pattern.patterns.flatMap(expandOrPattern);
}
// Recursively expand in sub-patterns
// ...
return [pattern];
}
// As-pattern: binds entire match to name
// (x :: xs) as list => (list, x)
function handleAsPattern(
pattern: AsPattern,
access: Access,
bindings: Map<string, Access>
): void {
// Bind the name to current access
bindings.set(pattern.name, access);
// Continue with inner pattern
extractBindings(pattern.pattern, access, bindings);
}
Workflow
- Define pattern syntax - Grammar for patterns
- Implement pattern parser - Parse patterns to AST
- Build exhaustiveness checker - Matrix-based analysis
- Add usefulness checker - Detect redundant patterns
- Implement decision tree compilation - Efficient matching
- Generate target code - From decision trees
- Handle guards - Conservative guard analysis
- Write tests - Exhaustiveness, compilation, runtime
Best Practices Applied
- Conservative exhaustiveness with guards
- Informative non-exhaustiveness witnesses
- Efficient decision tree compilation
- Proper binding extraction order
- Support for nested patterns
- Clear redundancy warnings
References
- Warnings for Pattern Matching (Maranget): https://moscova.inria.fr/~maranget/papers/warn/
- Compiling Pattern Matching: https://www.cs.tufts.edu/~nr/cs257/archive/luc-maranget/jun08.pdf
- Rust Pattern Matching: https://doc.rust-lang.org/reference/patterns.html
- OCaml Pattern Matching: https://ocaml.org/docs/pattern-matching
Target Processes
- pattern-matching-implementation.js
- parser-development.js
- code-generation-llvm.js
- interpreter-implementation.js
Signals
- GitHub stars
- 2k
- Forks
- 112
- Last commit
- Sep 2026
Advanced
- Item type
- skill
- Key
pattern-matching- Source
- github.com/a5c-ai/babysitter
Related picks
Skill · thedaviddias
The pick for JavaScriptmodern-javascript-patterns
Skill · wshobson
The pick for JavaScriptomh-rust
Skill · rlaope
The pick for Rustrust-sdk-specialist
Skill · a5c-ai
The pick for Rustsetup-ts-deep-modules
Skill · mattpocock
The pick for TypeScripttypescript-pro
Skill · jeffallan
The pick for TypeScript