I submitted this because I've been getting really interested in effect systems, especially now that OCaml 5 has a working production quality example they'd been iterating on for years prior. I wanted to see what it'd look like in Rust too so maybe one day we can get rid of async function coloring, and with OxCaml by Jane Street maybe we could see how that would look in practice.
Another reason for submitting this is that React actually has a quite robust effect system, that people don't necessarily realize they're using one every day if they use hooks.
I've been using it for 5+ years and my 4 men team can scale to supporting 6 different products (each running millions $ in business, sometimes daily), as we reuse the same patterns and architecture. This would not be possible without Effect, even though I'm lucky to have terrific engineers as colleagues, we just wouldn't be able to without the endless goodies from Effect.
The amount of features is basically endless, as effects and runtimes weren't enough, from SQL to AI, from effectful schemas (encoders/decoders), first-class OTEL support, CLI, debuggers, editor extensions, and many others. There's still countless modules I have yet to see or use.
Runtimes are available for each platform, including cloudflare workers.
There's absolutely nothing in TypeScript land to have such a wide scope.
v4 will also bring durable workflows (I'm already using v4 beta and that feature in prod) and many other goodies. That's quite important for us needing to have procedures that need to survive redeploys, crashes, etc.
I would never go back to writing standard TypeScript.
There is a learning curve, but you can adopt it incrementally. Nobody adopting it has ever gone back.
That being said, it would be great if there was a proper effect-based language (I've seen few projects like Effekt, but there's way too many things missing) as TypeScript is verbose, and effect adds its own verbosity.
I know parts of Effect like its schema are incrementally adoptable but if you use it substantially with many of its features, isn't it viral in a sense? In that you need to do things the Effect way and wrap libraries into Effect functions?
No ASM involved so technically portable (although it depends on built-in).
Flix equivalent (copy paste to https://play.flix.dev/):
eff Pick {
def pick(): Int32
}
def body(): (Int32, Int32, Int32) \ Pick = {
let a = Pick.pick();
let b = Pick.pick();
let c = Pick.pick();
(a, b, c)
}
def handlePick(f: Unit -> a \ ef): List[a] \ ef - Pick =
run {
f() :: Nil
} with handler Pick {
def pick(_, resume) =
resume(1) ::: resume(2) ::: resume(3)
}
def main(): Unit \ IO =
println(handlePick(body))
HeyImAlex•59m ago
codebje•39m ago
But you can have generic effects. Your arguments and return type can specify "any effect", indicating your function can use a type with any effect safely, or can be used in any effect context safely.
Passing an async value to a function doesn't mean that function must now also be an async function. It can be a "for all effects, do the thing" function. The code duplication problem is gone.
mrkeen•35m ago
Someone writes a post lamenting red and blue functions, and everyone eats it up.
Substitute colour for something meaningful and the idea becomes idiotic.
"Top level function declares that it is non-blocking, but when I try to call a small blocking function from it, I have to change the declaration to blocking???"
Yes, yes you do.
Total functions can't call non-total functions.
Deterministic functions can't call nondeterministic functions.
Non-IO functions can't call IO functions.
brabel•26m ago
https://www.unison-lang.org/
https://flix.dev/