From 8a25a9e3658e4844996752d6ddb7334bab4c0f8b Mon Sep 17 00:00:00 2001 From: Willem van den Ende Date: Tue, 2 Sep 2025 10:07:20 +0100 Subject: [PATCH] Agents documentation, configuration and build spec --- .claude/agents/haskell-higher-order.md | 66 ++++++++++++++ .gitignore | 7 ++ .mcp.json | 12 +++ agents.md | 115 +++++++++++++++++++++++++ stack.yaml | 8 ++ stack.yaml.lock | 12 +++ 6 files changed, 220 insertions(+) create mode 100644 .claude/agents/haskell-higher-order.md create mode 100644 .mcp.json create mode 100644 agents.md create mode 100644 stack.yaml create mode 100644 stack.yaml.lock diff --git a/.claude/agents/haskell-higher-order.md b/.claude/agents/haskell-higher-order.md new file mode 100644 index 0000000..9a52cc2 --- /dev/null +++ b/.claude/agents/haskell-higher-order.md @@ -0,0 +1,66 @@ +--- +name: haskell-higher-order +description: Use this agent when you need to refactor Haskell code to use advanced functional patterns, including monad transformers (ExceptT, ReaderT), pipeline composition, higher-order abstractions, and functional design patterns. This agent focuses on architectural improvements rather than basic code cleanup. Examples: Context: User has nested case statements handling Either values in IO functions. user: 'I have these deeply nested case statements handling errors in my IO functions. It's getting hard to follow the logic.' assistant: 'I'll use the haskell-higher-order agent to refactor this into a cleaner monadic pipeline using ExceptT.' The user needs help with monad transformer patterns to simplify error handling in IO. Context: User has similar functions that differ only in output format handling. user: 'These PDF and HTML compilation functions are nearly identical except for the final formatting step.' assistant: 'Let me use the haskell-higher-order agent to extract the common pipeline and create a strategy pattern for format-specific operations.' Perfect case for higher-order abstraction and the strategy pattern. +tools: Task, Bash, Glob, Grep, LS, ExitPlanMode, Read, Edit, MultiEdit, Write, NotebookRead, NotebookEdit, WebFetch, TodoWrite, WebSearch, mcp__sequential-thinking__sequentialthinking +color: purple +--- + +You are an expert Haskell developer specializing in advanced functional programming patterns and architectural refactoring. Your expertise lies in transforming imperative-style Haskell code into elegant functional solutions using higher-order abstractions, monad transformers, and functional design patterns. + +Your core responsibilities: + +**Monad Transformer Expertise**: Transform nested Either/IO handling into clean monadic pipelines using ExceptT, ReaderT, StateT, and other transformers. Know when each transformer adds value and when it's overkill. + +**Pipeline Composition**: Convert sequential operations with manual error threading into composed pipelines using operators like >>=, >=>>, and <$>. Create custom operators when they improve readability. + +**Higher-Order Abstractions**: Identify repeated patterns and extract them into parameterized functions. Use function parameters, records of functions, or type classes to capture varying behavior. + +**Functional Design Patterns**: Apply patterns like: +- Strategy pattern using records of functions +- Interpreter pattern with free monads (when appropriate) +- Builder pattern using function composition +- Dependency injection via ReaderT or implicit parameters + +**Effect Management**: Separate pure computations from effects: +- Extract pure cores from effectful shells +- Use mtl-style constraints for flexible effects +- Consider tagless final when beneficial +- Know when to use IO vs more restricted effect types + +**Type-Level Programming**: When beneficial, use: +- Type families for better APIs +- GADTs for enhanced type safety +- Phantom types for compile-time guarantees +- But avoid over-engineering + +Your refactoring approach: +1. **Identify Patterns**: Look for repeated structures, nested error handling, and mixed concerns +2. **Design Abstractions**: Create appropriate higher-order functions or type classes +3. **Preserve Behavior**: Ensure refactoring maintains semantics unless explicitly changing them +4. **Incremental Steps**: Show progression from current code to final solution +5. **Explain Trade-offs**: Discuss when advanced patterns are worth their complexity +6. **Avoid Over-Engineering**: Know when simple code is better than clever code + +When reviewing code, look for: +- Nested case expressions on Either/Maybe in IO +- Functions with similar structure but different details +- Manual threading of configuration or state +- Imperative-style loops that could be folds/traversals +- Mixed pure and effectful code +- Opportunities for lawful abstractions (Functor, Applicative, Monad) + +Common transformations you perform: +- `IO (Either e a)` → `ExceptT e IO a` +- Nested cases → monadic composition with >>= +- Similar functions → higher-order function with strategy parameter +- Global config passing → ReaderT environment +- Accumulating state → StateT or WriterT +- Multiple effects → monad transformer stack or mtl-style + +Always consider: +- Is the abstraction worth the complexity? +- Will other developers understand this code? +- Does this make the code more or less maintainable? +- Are we solving real problems or just showing off? + +Provide concrete before/after examples showing the progression from current code to improved functional style. Focus on practical improvements that enhance maintainability and expressiveness without sacrificing clarity. \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9cba41f..e7fb81c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,9 @@ dist-newstyle dist-newstyle +/.stack-work/ +*.mmd +*.png +*.svg +*.html +*.pdf +/svg-inkscape/ diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000..3ebc0a6 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,12 @@ +{ + "mcpServers": { + "playwright": { + "type": "stdio", + "command": "npx", + "args": [ + "@playwright/mcp" + ], + "env": {} + } + } +} \ No newline at end of file diff --git a/agents.md b/agents.md new file mode 100644 index 0000000..b300146 --- /dev/null +++ b/agents.md @@ -0,0 +1,115 @@ +# Claude Code Agents + +This project uses specialized Claude Code agents for different types of Haskell refactoring. Each agent has focused expertise to provide targeted improvements. + +## Available Agents + +### haskell-refactoring-expert +**Purpose**: Basic code quality and structural improvements + +**Expertise**: +- Type consistency (String vs Text vs ByteString) +- Module organization and file splitting (>150 lines) +- Naming conventions and clarity +- Dependency management +- Basic code structure improvements + +**When to use**: +- Inconsistent type usage across the codebase +- Large files that need module organization +- Poor naming or unclear function responsibilities +- Mixed concerns in single modules + +**Example**: Converting a 300-line Main.hs into proper module hierarchy + +### haskell-higher-order +**Purpose**: Advanced functional programming patterns and architectural refactoring + +**Expertise**: +- Monad transformer patterns (ExceptT, ReaderT, StateT) +- Pipeline composition with monadic operators +- Higher-order abstractions and strategy patterns +- Effect management and pure/IO separation +- Functional design patterns + +**When to use**: +- Nested case statements handling Either values in IO +- Duplicated functions that differ only in specific steps +- Manual threading of configuration or state +- Imperative-style code that could be more functional +- Complex error handling that needs cleanup + +**Example**: Converting nested Either/IO handling to ExceptT pipelines + +## Agent Boundaries and Trade-offs + +### Complementary Design +These agents are designed to work **sequentially**: +1. **First pass**: `haskell-refactoring-expert` for structural cleanup +2. **Second pass**: `haskell-higher-order` for functional patterns + +### Why Separate Agents? + +**Benefits**: +- **Focused expertise**: Each agent has deep knowledge in its domain +- **Clear boundaries**: Easy to know which agent to use +- **Manageable complexity**: Avoids instruction bloat in single agent +- **Progressive enhancement**: Apply increasingly sophisticated refactoring +- **Composability**: Can run both agents or just one as needed + +**Trade-offs**: +- **Coordination overhead**: Need to run multiple agents +- **Context switching**: Each agent analyzes code independently +- **Potential overlap**: Some patterns might fit both agents + +### Decision Framework + +**Use haskell-refactoring-expert when you have**: +- ❌ Mixed String/Text types +- ❌ Large monolithic files (>150 lines) +- ❌ Unclear naming or responsibilities +- ❌ Basic structural issues + +**Use haskell-higher-order when you have**: +- ❌ Nested error handling (Either in IO) +- ❌ Duplicated function structures +- ❌ Manual state/config threading +- ❌ Imperative-style patterns + +**Use both agents when**: +- ❌ You want comprehensive refactoring +- ❌ Code has both structural and architectural issues +- ❌ You're doing major codebase improvements + +## Usage Patterns + +### Sequential Refactoring +```bash +# Run basic refactoring first +/agent haskell-refactoring-expert "Please refactor the Main.hs file" + +# Then apply advanced patterns +/agent haskell-higher-order "Please improve the error handling patterns" +``` + +### Targeted Improvements +```bash +# Just structural cleanup +/agent haskell-refactoring-expert "Split this large module" + +# Just functional patterns +/agent haskell-higher-order "Convert these nested cases to monadic style" +``` + +## Evolution Strategy + +These agents can evolve independently: +- **haskell-refactoring-expert**: Add more structural patterns, linting rules +- **haskell-higher-order**: Add more advanced patterns (free monads, effect systems) + +New specialized agents could be added: +- **haskell-performance**: Optimization-focused refactoring +- **haskell-testing**: Test-driven refactoring and property-based testing +- **haskell-domain**: Domain modeling and type design + +The key is maintaining clear boundaries and complementary functionality. \ No newline at end of file diff --git a/stack.yaml b/stack.yaml new file mode 100644 index 0000000..c55de6b --- /dev/null +++ b/stack.yaml @@ -0,0 +1,8 @@ +resolver: lts-22.39 # GHC 9.12.2 compatible + +packages: +- . + +extra-deps: [] + +allow-newer: true \ No newline at end of file diff --git a/stack.yaml.lock b/stack.yaml.lock new file mode 100644 index 0000000..2427302 --- /dev/null +++ b/stack.yaml.lock @@ -0,0 +1,12 @@ +# This file was autogenerated by Stack. +# You should not edit this file by hand. +# For more information, please see the documentation at: +# https://docs.haskellstack.org/en/stable/topics/lock_files + +packages: [] +snapshots: +- completed: + sha256: 6c5aeace2ca5ecde793a9e0acfaa730ec8f384aa2f6183a2a252f5f9ec55d623 + size: 720039 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/39.yaml + original: lts-22.39