From e0272e9493a244ba2faf5988ebb2f0f12a9755d8 Mon Sep 17 00:00:00 2001 From: Magnus Madsen Date: Sun, 15 Mar 2026 10:58:15 +0100 Subject: [PATCH 1/2] feat: add anti-pattern sections to for-llms.md (#307) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add two new sections warning LLMs against common mistakes: - "Don't Nest `run` Blocks" — use a single `run` with chained handlers - "Don't Write CPS" — use effects and handlers instead of callbacks Co-Authored-By: Claude Opus 4.6 (1M context) --- src/for-llms.md | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/src/for-llms.md b/src/for-llms.md index b4c35a43..e79ef313 100644 --- a/src/for-llms.md +++ b/src/for-llms.md @@ -121,6 +121,93 @@ def main(): Unit \ IO = Note: Always write `with handler EffectName`, not just `with EffectName`. Multiple handlers are chained: `with handler A { ... } with handler B { ... }`. +## Don't Nest `run` Blocks + +When handling multiple effects, use a **single** `run` block with chained +`with handler` clauses. Do **not** nest `run` blocks inside each other. + +❌ **Incorrect:** + +``` +def main(): Unit \ IO = + run { + run { + greeting() + } with handler Ask { + def ask(_, k) = k("James Bond") + } + } with handler Say { + def say(s, k) = { println(s); k() } + } +``` + +✅ **Correct:** + +```flix +def main(): Unit \ IO = + run { + greeting() + } with handler Ask { + def ask(_, k) = k("James Bond") + } with handler Say { + def say(s, k) = { println(s); k() } + } +``` + +Note: A single `run` block can have multiple `with handler` clauses chained +one after another. There is no need to nest `run` blocks. + +## Don't Write CPS — Use Effects and Handlers + +Do **not** simulate effects by writing continuation-passing style (CPS) code +where handler functions take callbacks. Flix has a built-in effect system — +use `run`/`with handler` blocks instead. + +❌ **Incorrect (manual CPS with nested callbacks):** + +``` +def handleSleep(f: Unit -> a \ { Sleep, ef }): a \ ef + IO = ... + +def withLogging(f: Unit -> a \ { Sleep, ef }): a \ ef + { Sleep, Logger } = ... + +def withJitter(factor: Float64, f: Unit -> a \ { Sleep, ef }): a \ ef + { Sleep, Random } = ... + +def main(): Unit \ { Logger, Random, Sleep, IO } = + handleSleep(() -> + withLogging(() -> + withJitter(0.2, () -> + println("Sleeping 3 times with ±20% jitter..."); + Sleep.sleep(seconds(1)); + Sleep.sleep(seconds(2)); + Sleep.sleep(seconds(3)); + println("Done!") + ) + ) + ) +``` + +✅ **Correct (effects and handlers):** + +```flix +use Math.Random +use Time.Duration.{seconds} +use Time.Sleep + +def main(): Unit \ { Logger, Random, Sleep, IO } = + run { + println("Sleeping 3 times with ±20% jitter..."); + Sleep.sleep(seconds(1)); + Sleep.sleep(seconds(2)); + Sleep.sleep(seconds(3)); + println("Done!") + } with Sleep.withJitter(0.2) + with Sleep.withLogging +``` + +Note: Effects and handlers let you write flat, sequential code. Use +`run { ... } with Handler.middleware` to compose handlers — never pass +callbacks to simulate what the effect system already provides. + ## Java Types Must Be Imported In Flix, Java classes must always be imported before they can be used. You cannot From 8420ee4526fb3bee1dbd1b8577f0cc84619832fb Mon Sep 17 00:00:00 2001 From: Magnus Madsen Date: Sun, 15 Mar 2026 11:01:02 +0100 Subject: [PATCH 2/2] refactor: use Sleep example in "Don't Nest run Blocks" section Replace the Ask/Say greeting example with the Sleep.withJitter/withLogging example for consistency with the CPS section. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/for-llms.md | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/src/for-llms.md b/src/for-llms.md index e79ef313..a92fbbc8 100644 --- a/src/for-llms.md +++ b/src/for-llms.md @@ -129,29 +129,38 @@ When handling multiple effects, use a **single** `run` block with chained ❌ **Incorrect:** ``` -def main(): Unit \ IO = +use Math.Random +use Time.Duration.{seconds} +use Time.Sleep + +def main(): Unit \ { Logger, Random, Sleep, IO } = run { run { - greeting() - } with handler Ask { - def ask(_, k) = k("James Bond") - } - } with handler Say { - def say(s, k) = { println(s); k() } - } + println("Sleeping 3 times with ±20% jitter..."); + Sleep.sleep(seconds(1)); + Sleep.sleep(seconds(2)); + Sleep.sleep(seconds(3)); + println("Done!") + } with Sleep.withJitter(0.2) + } with Sleep.withLogging ``` ✅ **Correct:** ```flix -def main(): Unit \ IO = +use Math.Random +use Time.Duration.{seconds} +use Time.Sleep + +def main(): Unit \ { Logger, Random, Sleep, IO } = run { - greeting() - } with handler Ask { - def ask(_, k) = k("James Bond") - } with handler Say { - def say(s, k) = { println(s); k() } - } + println("Sleeping 3 times with ±20% jitter..."); + Sleep.sleep(seconds(1)); + Sleep.sleep(seconds(2)); + Sleep.sleep(seconds(3)); + println("Done!") + } with Sleep.withJitter(0.2) + with Sleep.withLogging ``` Note: A single `run` block can have multiple `with handler` clauses chained