Get the FREE Ultimate OpenClaw Setup Guide →

kotlin-functional-programming

npx machina-cli add skill msewell/agent-stuff/kotlin-functional-programming --openclaw
Files (1)
SKILL.md
4.4 KB

Kotlin Functional Programming

Workflow

  1. Read the relevant reference file(s) from references/ before advising (see References section below for which file covers which topics).
  2. Identify which principles apply to the user's code or question (see Summary of Principles in the reference).
  3. Apply the relevant best practices; cite section numbers when explaining trade-offs.
  4. Prefer Kotlin built-in features over third-party libraries unless the user explicitly asks otherwise.
  5. Validate suggestions against the Kotlin 2.0–2.2+ feature set described in the reference.
  6. When refactoring existing code, make the smallest change that moves toward the functional core, imperative shell architecture.

Key Principles (quick reference)

  • Default to val; treat var as a code smell requiring justification.
  • Write pure functions for all domain logic; push I/O and mutation to the edges.
  • Use if, when, try as expressions that return values assigned to val.
  • Model variants with sealed interface; never add else to an exhaustive when.
  • Wrap primitives in @JvmInline value class to prevent argument-order bugs at zero runtime cost.
  • Handle expected failures with T?, Result<T>, or sealed error hierarchies — not exceptions.
  • Compose behavior with higher-order functions; use inline on lambda-taking utilities to eliminate allocation overhead.
  • Build data pipelines with collection operators (map, filter, fold, flatMap, …).
  • Default to eager collections; switch to Sequence only for large datasets with multiple chained operations.
  • Use tailrec for linear recursion, DeepRecursiveFunction for tree/graph recursion.
  • Model async work with suspend functions and Flow pipelines; prefer coroutineScope over GlobalScope.
  • Use context parameters (Kotlin 2.2+) sparingly for cross-cutting concerns (Raise, logging, transaction scope).

Common Tasks

Writing pure domain logic

Follow §2 (Pure Functions), §3 (Immutability), §17 (Functional Core, Imperative Shell).
Pass all dependencies as parameters; return new values instead of mutating inputs.

Modeling a domain with types

Follow §5 (Sealed Types), §6 (Value Classes).
Prefer sealed interface over sealed class unless subtypes share state.
Add validation in value class init blocks ("parse, don't validate").

Error handling

Follow §7 (Functional Error Handling).

  • Absence/not-found → nullable T?
  • Wrapping throwing APIs → Result<T> + runCatching
  • Typed domain errors → custom sealed hierarchy + minimal Either<L, R>

Collection pipelines

Follow §12 (Collections) and §13 (Sequences).
Prefer named operations over manual loops.
Use fold over reduce when an initial value is needed or the result type differs.

Testing

Follow §18 (Testing).

  • Test pure core with direct assertions — no mocks needed.
  • Test sealed branches exhaustively.
  • Use Kotest checkAll with Arb for property-based testing of validators and transformations; prefer checkAll over forAll for matcher-based assertions and clearer failures.
  • Reserve integration tests (MockK, Testcontainers) for the imperative shell.

References

Source

git clone https://github.com/msewell/agent-stuff/blob/main/skills/kotlin-functional-programming/SKILL.mdView on GitHub

Overview

This skill teaches writing idiomatic, functional-style Kotlin by leveraging built-in language features. It covers immutability, pure functions, sealed types, functional error handling, collection pipelines, coroutines, and functional architecture patterns to help you build robust, testable code.

How This Skill Works

Follow the workflow: read relevant references, map applicable principles to your code, and apply Kotlin’s built-in features. Emphasize val over var, use sealed interfaces for variants, and handle errors with Result, T?, or sealed hierarchies; compose behavior with map/flatMap/fold and prefer eager collections unless sequences are beneficial.

When to Use It

  • You want a pure, testable domain logic without side effects.
  • You’re refactoring existing code toward a functional core and an imperative shell.
  • You need strong type safety with sealed types for domain variants.
  • You’re handling errors functionally (using Result, nullable types, or sealed error hierarchies) instead of exceptions.
  • You’re building data pipelines with collection operators (map, filter, fold, flatMap) and deciding when to use List vs. Sequence.

Quick Start

  1. Step 1: Identify the pure core vs. IO/side-effect edges in your codebase.
  2. Step 2: Refactor domain logic into pure functions that take inputs and return new values.
  3. Step 3: Introduce functional error handling (Result, T?, or sealed errors) and fold in coroutines/Flow as needed.

Best Practices

  • Prefer val over var and push mutation toward the edges of the system.
  • Write pure domain logic; pass all dependencies as parameters and return new values.
  • Model variants with sealed interfaces; avoid else branches in exhaustive when expressions.
  • Use collection operators to build pipelines; use fold when an initial value or differing result type is needed.
  • Default to eager collections; switch to Sequence only for large datasets with multiple chained operations.

Example Use Cases

  • A domain service that computes discounts using pure functions, independent of IO.
  • Modeling a user action hierarchy with a sealed interface to represent all possible events.
  • Wrapping a legacy IO API with Result and runCatching to expose a safe, functional surface.
  • Transforming streaming data with map/flatMap to produce a clean data pipeline.
  • Tail-recursive traversal of a tree using @tailrec to safely compute aggregates.

Frequently Asked Questions

Add this skill to your agents

Related Skills

creating-c4-diagrams

msewell/agent-stuff

Creates, reviews, and interprets C4 software architecture diagrams (System Context, Container, Component, Dynamic, Deployment). Produces Structurizr DSL or Mermaid diagram code following C4 model best practices. Use when creating architecture diagrams for a system, reviewing existing C4 diagrams for correctness and anti-patterns, generating Structurizr DSL workspaces, producing Mermaid C4 diagrams for READMEs, or using C4 diagrams as context for design decisions, code generation, risk analysis, or onboarding.

arazzo-specification

msewell/agent-stuff

Guides writing, reviewing, and modifying Arazzo workflow specifications (OpenAPI Initiative standard for multi-step API workflows). Use when creating Arazzo documents from scratch, adding steps or workflows to existing specs, reviewing Arazzo files for correctness, or generating API workflow definitions. Covers document structure, runtime expressions, success criteria, control flow, data threading, reusable components, workflow composition, AI agent integration, and validation.

property-based-testing-with-kotest

msewell/agent-stuff

Writes property-based tests using Kotest's kotest-property module. Identifies testable properties, designs generators, and configures PBT for Kotlin/JVM projects. Use when writing property-based tests, creating custom Arb generators, choosing property patterns (roundtrip, invariant, idempotence, oracle), debugging shrunk counterexamples, or integrating PBT into a Kotlin test suite alongside example-based tests.

reducing-coupling

msewell/agent-stuff

Analyzes a codebase scope for coupling issues, diagnoses coupling types using the Connascence framework, and proposes a comprehensive refactoring plan with concrete code changes. Use when asked to find coupling, reduce dependencies, decouple modules, or improve modularity in a codebase.

mermaid-sequence-diagrams

msewell/agent-stuff

Generates, reviews, and fixes Mermaid sequence diagrams following syntax rules and best practices. Use when creating sequence diagrams from system descriptions, reviewing existing Mermaid sequence diagrams for correctness, fixing parse errors, or refactoring large diagrams into focused sub-diagrams. Covers participants, arrows, activations, control flow, notes, styling, and common anti-patterns.

making-invalid-states-unrepresentable

msewell/agent-stuff

Analyzes existing code and guides new type design to make invalid states unrepresentable using type system techniques such as sum types, newtypes, typestate, branded types, and parse-don't-validate. Use when reviewing code for invalid-state bugs, refactoring types to eliminate impossible states, designing domain models, or applying compile-time correctness patterns. Language-agnostic.

Sponsor this space

Reach thousands of developers