hagler ~/learn$cat cheat-sheet.md

Promise vs. Effect, on One Page

QuestionPromise (the receipt)Effect (the recipe card)
What is it?A value that isn’t ready yetA plan for getting a value
When does it start?The moment you make itOnly when you run it
Can you run it twice?No, one receipt = one smoothieYes, as many times as you like
Does the type say what can go wrong?No, Promise<Smoothie>Yes, Effect<Smoothie, OutOfMango>
Does the type say what it needs?NoYes, Effect<Smoothie, OutOfMango, Blender>
Can you cancel it?NoYes, interrupt the fiber, cleanup still runs
Write steps top to bottomasync / awaitEffect.gen / yield*
“Do this when it succeeds”.then(f)Effect.map / Effect.andThen
“Do this if it fails”.catch(f) (catches everything, mystery box)Effect.catchTag("Name", f) (one specific error) or Effect.catch (all listed errors)
Try again on failureWrite a loop yourselfEffect.retry(card, { times: 3 })
Give up after a whileHard, needs a second Promise and a timerEffect.timeout(card, "2 seconds")
Several at oncePromise.all([...])Effect.all([...], { concurrency: n })
First one winsPromise.race([...]) (loser keeps running)Effect.race(a, b) (loser is interrupted)
Always clean uptry { } finally { } (no interrupt case)Effect.acquireRelease (success, error, and interrupt)
Ask for a helperImport it or pass it in by handyield* Blender, then Effect.provide(layer)
Turn it into the other(a Promise is already “running”)Effect.runPromise(card) at the door of the program

Reading an Effect type out loud

Effect<Smoothie, OutOfMango, Blender>

“An Effect that gives you a Smoothie, might fail with OutOfMango, and needs a Blender.”

  • never in slot 2: nothing can go wrong.
  • never in slot 3: needs nothing. Ready to run.
  • Trailing nevers can be left off: Effect<number> means Effect<number, never, never>.

The five lines of Effect 4 you actually need this month

import { Effect, Console, Context, Layer, Data, Fiber } from "effect"

Effect.gen(function* () { const x = yield* step; return x })   // a recipe with steps
class OutOfMango extends Data.TaggedError("OutOfMango") {}     // a named error
class Blender extends Context.Service<Blender, { ... }>()("Blender") {}   // a needed thing
Layer.succeed(Blender, { ... })                                 // a way to provide it
Effect.runPromise(card.pipe(Effect.provide(layer)))            // the door out of the kitchen

hagler ~$