[{"data":1,"prerenderedAt":4},["ShallowReactive",2],{"8tZqxc9iZl":3},"# LeanEff\n\nLeanEff is a small Lean 4 extensible-effects library inspired by\n“Freer Monads, More Extensible Effects,” and shaped for practical Lean\nprogramming.\n\nThe intended user-facing style is concrete effect rows:\n\n```lean\nimport LeanEff\n\nopen LeanEff\n\ndef program : Eff [Reader Nat, Writer String] Nat := do\n  let n ← ask\n  tell s!\"n = {n}\"\n  pure (n + 1)\n\n#eval program\n  |> runReader 41\n  |> runWriter\n  |> run\n```\n\nEffect rows are treated as set-like lists for handler lookup. A handler removes\nits effect wherever it appears and preserves the remaining row order; the order\nin which handlers are called controls effect interaction.\n\n## Included Effects\n\n- `Reader ρ`: `ask`, `runReader`\n- `Writer ω`: `tell`, `runWriter`\n- `State σ`: `get`, `put`, `modify`, `runState`, `evalState`, `execState`\n- `ExceptE ε`: `throw`, `tryCatch`, `runExcept`\n- `Random`: `randNat`, `randBool`, `runRandom`, `evalRandom`\n- `LiftIO`: `liftIO`, `runLiftIO`\n- `Clock τ`: `now`, `runClockAt`\n- `Console`: `printLine`, `readLine`, `runConsoleIO`\n- `Display frame`: `drawFrame`, `runDisplayIO`\n- `Input ι`: `pollInput`\n- `Sleep`: `sleepMs`, `runSleepIO`\n\n## Debug Snapshots\n\n`recordSnapshot` records request/response effect interactions into a\n`Snapshot`. A snapshot can later replay the same responses with\n`replaySnapshot`, run a deterministic check with `checkSnapshot`, or be compared\nagainst another run with `compareSnapshots`. Use `Snapshot.toJsonString` and\n`Snapshot.fromJsonString` to persist traces as JSON.\n\n```lean\ndef recorded :=\n  program\n    |> recordSnapshot\n    |> runReader 41\n    |> runWriter (ω := String)\n    |> runWriter (ω := SnapshotEvent)\n    |> run\n\ndef replayed :=\n  program\n    |> replaySnapshot recorded.2\n\ndef checked :=\n  program\n    |> checkSnapshot recorded.2\n\ndef divergence :=\n  compareSnapshots recorded.2 anotherSnapshot\n```\n\nEffects opt into snapshots through `SnapshotCodec`, which encodes effect\nrequests and responses as structured `Lean.Json` values. LeanEff includes\ncodecs for the built-in resumable effects.\nSnapshots are request/response traces, so an effect operation that never resumes\ndoes not produce an event through this middleware. During a check, recorded\nresponses drive input-like effects such as `Random` and `Input`, while\noutput-like effect requests such as `Display.draw` frames must match the\nrecorded snapshot. `SnapshotCodec.checkMode` controls whether a request replays\nits recorded response or asserts the generated request.\n\n## Examples\n\n- `Examples.AsciiTetris`: an animated terminal Tetris clone with nonblocking\n  controls, ANSI colors, and a next-piece preview. It uses `Reader` for\n  configuration, `State` for the board, `Writer` for game events, `ExceptE` for\n  quit/game-over exits, `Random` for piece generation, `Display String` for\n  drawing, `Input Command` for controls, and `Sleep` for frame pacing.\n\nRun it with:\n\n```sh\nlake exe ascii_tetris\n```\n\nRecord a JSON snapshot for deterministic debugging with:\n\n```sh\nlake exe ascii_tetris --record trace.json\n```\n\nAnimate a JSON snapshot by replaying the recorded keys with:\n\n```sh\nlake exe ascii_tetris --replay trace.json\n```\n\nStrictly verify a JSON snapshot without animation with:\n\n```sh\nlake exe ascii_tetris --check trace.json\n```\n\nRun it in a real terminal because it temporarily switches terminal input mode.\n\n- `Examples.VideoRental`: a small \"Palladin's Video Rental\" shop. The business\n  logic uses `Clock` for the current rental day, `RentalRepo` for customers,\n  movies, and rentals, and `Writer String` as a notification outbox. The demo\n  interpreter backs the repository with an initialized in-memory SQLite database\n  through `leanprover/leansqlite`, then runs an interactive menu until quit.\n\nRun it with:\n\n```sh\nlake exe video_rental_shop\n```\n\n- `Examples.AgentSnake`: a concurrent multi-agent snake arena. The arena uses\n  an `AgentHost` effect to spawn AI agents, publish world snapshots, and gather\n  agent moves. Each AI snake is an independent `AgentEff` program that observes\n  snapshots and chooses moves. `Random` drives agent jitter and food placement,\n  snakes render as colored `*` cells, and the same effects can run with either a\n  threaded host interpreter or a single-threaded cooperative interpreter.\n\nRun it with:\n\n```sh\nlake exe agent_snake_arena\n```\n\nUse the single-threaded cooperative interpreter with:\n\n```sh\nlake exe agent_snake_arena --cooperative\n```\n\nRecord a JSON snapshot of the arena with:\n\n```sh\nlake exe agent_snake_arena --record trace.json\n```\n\nReplay the recorded snake animation with:\n\n```sh\nlake exe agent_snake_arena --replay trace.json\n```\n\nStrictly verify the snapshot without animation with:\n\n```sh\nlake exe agent_snake_arena --check trace.json\n```\n\n## V1 Notes\n\n- Duplicate effect labels are unsupported. Wrap labels in distinct types if two\n  effects have the same payload type.\n- The core uses a Lean-friendly mutual `Eff` / `Arrs` continuation queue with\n  a `ViewL` operation, so continuations are consumed from the front instead of\n  repeatedly walking a left spine.\n- Recursive handlers are executable `partial def`s; v1 handlers therefore\n  require inhabited result types.\n",1780241993920]