logoalt Hacker News

tometoday at 7:03 AM0 repliesview on HN

It's debatable how much one is willing to describe historical solutions like MTL style to be a "good" solution to this problem (I explained the downsides in my talk "A History of Effect Systems"[1] at Zurihac 2025), but I certainly have no hesitation in describing my capability-based effect system Bluefin[2], as a good solution.

For the channels you describe above the type signature would look like this

    Yield String e1 -> -- stdout
    Await String e2 -> -- stdin
    Yield String e3 -> -- logging
    Network e4 -> -- network
    Database e5 -> -- database
    FileSystem e6 -> -- file system
    Eff es r
Six different capabilities that give you access to six different channels of IO. A "Yield" to which you yield strings to stdout, an "Await" from which you can await strings from stdin, a "Yield" to which you yield log messages, and three abstract effects that allow you to do network, database and file system operations (abstract because I'm not sure exactly how you want them defined, but there's an example of the implementation of a file system effect at https://hackage-content.haskell.org/package/bluefin-0.6.0.0/...).

No problem with combining or untangling monads whatsoever. This is the natural conclusion of galaxyLogic's point: instead of dividing your program into two parts (IO and not IO) you divide it into six parts (or maybe 2^6 parts?) according to which fine grained effects you have in scope.

If you (or anyone) has any questions about Bluefin I'm happy to help. Please feel free to ask here or on the issue tracker[3].

[1] https://www.youtube.com/watch?v=RsTuy1jXQ6Y

[2] https://hackage.haskell.org/package/bluefin

[3] https://github.com/tomjaguarpaw/bluefin/issues/new