Back to Skills

effects

verified

OCaml 5 algebraic effects design patterns. Use when Claude needs to: (1) Design APIs that interact with effect-based schedulers, (2) Decide between effects vs exceptions, (3) Integrate libraries with Eio or affect, (4) Handle suspension vs error cases in streaming code, (5) Understand the layered effect design principle

View on GitHub

Marketplace

ocaml-claude-marketplace

avsm/ocaml-claude-marketplace

Plugin

ocaml-dev

development

Repository

avsm/ocaml-claude-marketplace
15stars

plugins/ocaml-dev/skills/effects/SKILL.md

Last Verified

January 20, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/avsm/ocaml-claude-marketplace/blob/main/plugins/ocaml-dev/skills/effects/SKILL.md -a claude-code --skill effects

Installation paths:

Claude
.claude/skills/effects/
Powered by add-skill CLI

Instructions

# OCaml 5 Effects Design

## Core Principle

**Effects for control flow, exceptions for errors.**

| Concern | Mechanism | Example |
|---------|-----------|---------|
| Suspension (wait for data) | Effects | `perform Block`, `perform Yield` |
| Error (EOF, malformed) | Exceptions | `raise End_of_file`, `Invalid_argument` |

## Layered Design

Effects should be handled at the **source level**, not in protocol parsers:

```
Application
    ↓
Protocol parser (Binary.Reader, Cbor, etc.)
    ↓  raises exceptions on EOF/error
bytesrw (effect-agnostic)
    ↓  just calls pull function
Source (Eio flow, affect fd, Unix fd)
    ↓  performs effects for suspension
Effect handler (Eio scheduler, affect runtime)
```

### Why This Matters

- **Parsers stay pure**: No effect dependencies, easy to test
- **Sources control blocking**: Handler decides wait vs fail vs timeout
- **Composability**: Same parser works with any effect system

## Effect Libraries

### Eio

Effects are internal to the scheduler. User code looks synchronous:

```ocaml
(* Reading blocks via internal effects *)
let data = Eio.Flow.read flow buf
```

### affect

Explicit effects for fiber scheduling:

```ocaml
type _ Effect.t +=
| Block : 'a block -> 'a Effect.t   (* suspension *)
| Await : await -> unit Effect.t    (* wait on fibers *)
| Yield : unit Effect.t             (* cooperative yield *)

(* Block has callbacks for scheduler integration *)
type 'a block = {
  block : handle -> unit;      (* register blocked fiber *)
  cancel : handle -> bool;     (* handle cancellation *)
  return : handle -> 'a        (* extract result *)
}
```

### bytesrw

Effect-agnostic streaming. The pull function you provide can perform any effects:

```ocaml
(* bytesrw just calls your function *)
let reader = Bytesrw.Bytes.Reader.make my_pull_fn

(* If my_pull_fn performs Eio effects, they propagate *)
(* If my_pull_fn performs affect Block, they propagate *)
(* bytesrw doesn't care - it just calls the function *)
```

## Integrat

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
3567 chars