$ cat learning-effect-7-the-third-slot.md
Part 7: The Third Slot
$ tail -f learning-effect-7-the-third-slot/readers
connecting…
The first two slots are easier to care about.
Effect.Effect<Success, Error, Requirements>;Success is what I want.
Error is what can go wrong.
The third slot is quieter.
It says what the program needs.
never means nothing is needed
Effect.Effect<number, InvalidUserId, never>;This can parse a number and fail with InvalidUserId.
It does not need a database, config, logger, or HTTP client.
So the requirement is never.
A real dependency shows up there
interface UserRepo { readonly findById: (id: number) => Effect.Effect<User, UserNotFound>;}A program that needs UserRepo has that in the type:
Effect.Effect<User, UserNotFound, UserRepo>;Read it as:
I can give you a User, I may fail with UserNotFound, and I need a UserRepo.
Why this matters
In normal code, dependencies hide in imports.
A function calls a module. The module reads config. The config reads env vars. Somewhere in there, the test gets annoying.
Effect makes the need visible.
That does not magically make the design good.
But it makes the hidden part harder to ignore.