Functional Programming at Arda
This document summarizes the functional programming (FP) patterns and techniques used across the Arda codebase, specifically within common-module, operations, and arda-frontend-app.
The codebase demonstrates a strong commitment to functional paradigms, particularly Railway Oriented Programming for error handling and Monadic composition for side effects (I/O).
For implementation code paths and “use when” guidance for specific patterns, see Implementation Patterns.
Backend (Kotlin) [BE]
Section titled “Backend (Kotlin) [BE]”1. Railway Oriented Programming (ROP) [BE]
Section titled “1. Railway Oriented Programming (ROP) [BE]”The most prevalent pattern is the use of the Result type to model success and failure, ensuring errors are handled explicitly as values rather than exceptions.
- Core Abstraction:
kotlin.Result<T> - Extensions:
cards.arda.common.lib.lang.ResultExt.kt - Key Operations:
flatMap: Chains operations that both returnResult, allowing short-circuiting on failuremapCatching: Wraps throwing code into aResultcollectAll: TransformsIterable<Result<T>>intoResult<List<T>>(all success or first failure)unitify: Discards the value, keeping the success/failure status
// Chaining validationsfun validate(input: Input): Result<Unit> { return validateFormat(input) .flatMap { validateBusinessRule(it) } .flatMap { validateConsistency(it) }}
// Aggregating results from a listval validItems: Result<List<Item>> = rawItems.map { validate(it) }.collectAll()This pattern is used throughout domain, service, and persistence code. For API-level error response conventions see Exception Handling.
2. The IO Monad Pattern (DBIO) [BE]
Section titled “2. The IO Monad Pattern (DBIO) [BE]”Database interactions are modeled as lazy, suspendable computations that return a Result. This separates the definition of an operation from its execution, allowing complex transaction scripts to be composed from smaller, reusable blocks before any I/O occurs.
- Core type:
typealias DBIO<R> = suspend () -> Result<R> - Location:
cards.arda.common.lib.persistence.types.DBIO.kt
Key Characteristics
Section titled “Key Characteristics”- Lazy: A
DBIOis just a function. Creating it does not execute the operation — it must be invoked to run. - Side-Effecting: Encapsulates I/O that can be executed in a transactional context using any Coroutine Executor.
- Fail-Safe: Wraps the result in
Result<R>, forcing explicit failure handling. - Suspendable: Supports Kotlin coroutines for non-blocking I/O.
DBIO Combinators
Section titled “DBIO Combinators”// map: transform the successful resultval getDoubleCount: DBIO<Int> = getCount.map { it * 2 }
// liftMap / flatMap: sequential dependencyval userPosts: DBIO<List<Post>> = findUser.liftMap { user -> findPosts(user) }
// then: sequence, ignoring first resultval loggedGetData: DBIO<Data> = logAccess.then(getData)
// both: zip two operationsval combined: DBIO<Pair<Int, String>> = op1.both(op2)
// validate and chainval op: DBIO<Entity> = validate(input).lift().then(createEntity(input))Transaction Management
Section titled “Transaction Management”DBIO operations are transaction-agnostic by default. They can be lifted into a transactional context using TDBIO:
typealias TDBIO<R> = suspend Transaction.() -> Result<R>transactional(): ConvertsDBIO<T>toTDBIO<T>io(tx): Runs aTDBIO<T>using a specific ExposedTransaction
Compose multiple DBIO operations, then execute them all within a single transaction at the Service or Endpoint layer.
Example: Composed Service Method
Section titled “Example: Composed Service Method”fun createWithDependent(parentPayload: Parent, childPayload: Child): DBIO<Pair<Parent, Child>> { val createParentOp = parentUniverse.create(parentPayload, ...) return createParentOp.liftMap { createdParent -> val childWithRef = childPayload.copy(parentId = createdParent.eId) childUniverse.create(childWithRef, ...).map { createdChild -> createdParent to createdChild } }}Usage in Universe Interface
Section titled “Usage in Universe Interface”interface Universe<EP, M> { suspend fun create(...): DBIO<BitemporalEntity<EP, M>> suspend fun read(...): DBIO<BitemporalEntity<EP, M>?> // ... other operations}Calling universe.create(...) does not write to the database. It returns a DBIO “program” that must be executed to apply the change.
3. Immutability and Data Classes [GEN]
Section titled “3. Immutability and Data Classes [GEN]”The domain model relies on immutable data structures.
- Technique:
data classwithvalproperties - Mutation: Via the
copy()method — creates a new instance with specific fields modified - Benefit: Thread safety and predictable state flow
// "Mutating" an immutable stateval resolvedDefaultSupply = when(payload.defaultSupply) { null -> primaryName ?: secondaryName else -> payload.defaultSupply}return payload.copy( primarySupply = payload.primarySupply?.copy(name = primaryName), defaultSupply = resolvedDefaultSupply)4. Partial Functions [BE]
Section titled “4. Partial Functions [BE]”The codebase implements a Scala-like PartialFunction abstraction, useful for defining logic that applies only to a subset of inputs.
- Location:
cards.arda.lang.PartialFunction.kt - Features:
isDefinedAt,orElse(composition) - Usage: Event handlers or state transitions where a handler only deals with specific event types
5. Functional State Machines [BE]
Section titled “5. Functional State Machines [BE]”The StateEngine library models state transitions as a composition of functions. States and transitions are declared with guard predicates and entry/exit actions; the engine generates executors from this declaration.
- Core type:
typealias Operation<...> = suspend CTX?.(...) -> Result<RESULT> - Location:
cards.arda.common.lib.service.stateengine - Code:
/common-module/lib/src/main/kotlin/cards/arda/common/lib/service/stateengine/StateEngine.kt
6. Higher-Order Functions [GEN]
Section titled “6. Higher-Order Functions [GEN]”Functions are first-class citizens and are often passed as arguments to parameterize behavior.
Example: validateSupply accepts iterables of validation functions or lambdas to customize strictness (checkAndVerify vs checkLaxConsistency).
Frontend (TypeScript / React) [FE]
Section titled “Frontend (TypeScript / React) [FE]”1. Functional Components [FE]
Section titled “1. Functional Components [FE]”UI logic is encapsulated in pure functional components that render based on props and hooks. State is local and managed via standard React hooks (useState, useReducer).
2. Declarative Data Transformations [FE]
Section titled “2. Declarative Data Transformations [FE]”Standard JavaScript array methods (map, filter, reduce) are preferred over imperative loops for rendering lists and transforming data.
Infrastructure (CDK / TypeScript) [GEN]
Section titled “Infrastructure (CDK / TypeScript) [GEN]”Functional Configuration and Data Flow
Section titled “Functional Configuration and Data Flow”The code strictly separates Data (Configuration) from Behavior (Constructs):
- Interfaces as Contracts: Inputs (
Props) and Outputs (Built,ExportValues) are defined asreadonlyinterfaces, enforcing immutability - Pure Transformation Functions: Complex logic is extracted into pure functions that transform data without side effects
Immutability
Section titled “Immutability”Property mutation is avoided:
- All properties in
PropsandBuiltinterfaces arereadonly - Helper functions like
safeSubstitutereturn new strings rather than mutating buffers
Separation of Concerns
Section titled “Separation of Concerns”- Static Validation:
validatePropsmethods are static pure functions that returnError[] - Logic Extraction: Heavy logic is moved out of constructors into private methods or external utilities
Summary Table [GEN]
Section titled “Summary Table [GEN]”| Concept | Backend (Kotlin) | Frontend (TypeScript) |
|---|---|---|
| Error Handling | Result<T> Monad (Railway Oriented) | Try/Catch, Promise Chains |
| Side Effects | DBIO (IO Monad), Coroutines | useEffect, Event Handlers |
| Immutability | data class, copy(), val | const, Spread operator ... |
| Collections | Extension functions (collectAll, map) | Array methods (map, filter) |
| State | StateEngine (Functional State Machine) | useState, useReducer |
Copyright: © Arda Systems 2025-2026, All rights reserved