skills/fp-skills/skills/fp-composition/SKILL.md
Build complex behavior by composing small, reusable functions. Covers currying, partial application, pipe/flow, data-last design, and building utility libraries from tiny pieces. Activate when: creating utility functions, building data processing pipelines, chaining transformations, refactoring large functions into smaller ones, or when the user mentions pipe, compose, curry, partial application, point-free, data-last, or function composition. Works in any language (TypeScript, Python, Go, Rust, Java).
npx skillsauth add olion500/skills fp-compositionInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Build complex behavior from small functions. Each does one thing. Combine into pipelines.
flow (create named reusable function). If one-off → pipe or inline.T → T (same type)? → Simple pipe. Mixed types → name intermediate steps for readability.pipe: transform a value now. flow: create a reusable function for later.
// pipe — immediate
const slug = pipe(" Hello World ", trim, toLowerCase, replaceSpaces);
// flow — reusable
const slugify = flow(trim, toLowerCase, replaceSpaces);
slugify(" Hello World "); // reuse many times
Implementation (no library needed):
const pipe = (value, ...fns) => fns.reduce((acc, fn) => fn(acc), value);
const flow = (...fns) => (value) => fns.reduce((acc, fn) => fn(acc), value);
Python: reduce(lambda acc, fn: fn(acc), fns, value). Rust: method chaining IS composition. Go: explicit function calls.
Convert f(a, b) into f(a)(b) to create specialized versions.
const withPrefix = (prefix: string) => (s: string) => `${prefix}${s}`;
const apiUrl = withPrefix("https://api.example.com");
apiUrl("/users"); // "https://api.example.com/users"
apiUrl("/products"); // "https://api.example.com/products"
// Practical: config-level currying
const fetchWithAuth = (token: string) => (method: string) => (url: string) =>
fetch(url, { method, headers: { Authorization: `Bearer ${token}` } });
const authedGet = fetchWithAuth(myToken)("GET");
authedGet("/api/users");
Python: functools.partial(fn, fixed_arg).
Put the data argument last. This makes functions composable with pipe/map.
// BAD: data-first — can't compose
const filterByAge = (users: User[], min: number) => users.filter(u => u.age >= min);
// GOOD: data-last — composes naturally
const filterByAge = (min: number) => (users: User[]) => users.filter(u => u.age >= min);
const getActiveAdults = flow(filterByAge(18), filterByActive(true), sortBy("name"));
Small curried functions compose into powerful domain logic:
const prop = (key) => (obj) => obj[key];
const gt = (min) => (n) => n > min;
const not = (fn) => (x) => !fn(x);
// Compose into domain logic
const isAdult = flow(prop("age"), gt(17));
const isGmail = flow(prop("email"), (s) => s.includes("@gmail"));
users.filter(isAdult);
users.filter(not(isGmail));
Insert tap to inspect intermediate values without breaking the chain:
const tap = (label) => (value) => { console.log(`[${label}]`, value); return value; };
const result = pipe(rawData, parseInput, tap("parsed"), validate, tap("validated"), transform);
Composition is NOT the right tool when:
fetchWith({ token, method, url })flow(prop("age"), gt(17)) is fine, flow(map(prop("x")), filter(gt(0)), reduce(add, 0)) is too muchdevelopment
Search and query Elasticsearch/Kibana database models using curl API. Use for querying database models, searching Kibana indices, checking Elasticsearch data, investigating data in Kibana, finding records by ID, searching documents. Supports multiple environments (dev, qa, stage, production-us, production-au, production-eu).
development
Search and analyze Datadog logs and metrics using API for cupixworks-api and cupixworks-worker services. Use when debugging errors, investigating issues, searching logs, analyzing worker jobs, checking Sidekiq logs, querying metrics, or finding specific log entries by class/function names. Supports error/warn/info log levels with 14-day retention for logs.
tools
Create, update, search, transition, link, and read comments on Jira issues via CLI. MUST use this skill whenever the user pastes or mentions any atlassian.net URL (Jira issues, Confluence pages, focusedCommentId links, board links — anything from *.atlassian.net). Also use for: TSLA-* ticket references, JQL searches, issue status changes, reading comments, creating bugs, updating descriptions. This is the ONLY way to interact with Jira/Atlassian — there is no MCP Atlassian available.
development
Search Cupix Watch (Kibana/Elasticsearch) application logs at watch.cupix.com. Use when the user asks to search logs, find errors, debug processing issues, or investigate service behavior. Triggers on keywords like "log", "watch", "kibana", "error log", service names (skat, pano, api, worker, vista), or mentions of cupix processing pipelines.