QuadrupleA 9 days ago

When I peek at the functional programming world through articles like this, I really question if it's a world drowning in its own self-created complexity.

The article states that side effects prevent us from achieving "reasoning" and "composition".

Wat?

Side effects are so scary and unapproachable that this crazy labyrinth of monads, purity rules, immutability, and the next big thing of direct-style effects is actually better?

Just do some reasoning about the side effects.

  • YorkshireSeason 9 days ago

    The purpose of effect handlers, direct-style effects etc, is to let the type-checker/type-inferencer do most of the reasoning about side-effects.

    Using such techniques requires an upfront investment of learning how this works, but once that mountain is climbed, programming becomes easier, faster and less error prone in many cases.

    • gsliepen 9 days ago

      I agree with it becoming less error prone and more composable. But faster and easier? The examples I've seen in this and other articles about effect systems use many more lines of code just to print a single line than you would use in a language like Python, and that's excluding the definition of the effect types themselves. Ideally, I'd like to get all the benefits of an effect system, but without the verboseness that seems to come with it.

      • YorkshireSeason 9 days ago

        Clearly, effect systems, as we know them today, are very heavyweight, and not worth the effort in the small. That's not controversial. But we have to present the ideas to beginners somehow. Those complex types come into their own in (some) large-scale programs, and especially as large-scale programs evolve, as they are being changed by programmers other than the original authors. (Not all programming tasks may be suitable, see the article on Rust for games programming that's on the front page RN.) All that said, the whole point of the article, and the research on direct style effects is to make effect typing much more lightweight. Effect types as we do them today metastasise along the call graph, and that is a big problem (this is also why Java-style exception specifications are considered a mistake). Direct-style effects essentially use implicit arguments, as popularised by Haskell and Scala, to hide much of this complexity. Whether this experiment will succeed, or direct style effects suffer from other problems is unclear and we have to wait until we have enough experience with them. And that can only start, once there is a language that implements support for first class direct style effects.

        The article suggests that this is coming to Scala, and I'm looking forward to being a guinea pig.

      • naasking 9 days ago

        > The examples I've seen in this and other articles about effect systems use many more lines of code just to print a single line than you would use in a language like Python

        This seems to me a bit like complaining that defining C functions and for-loops are so much more verbose than just using JMP instructions in assembly language, so why go to all the trouble of bothering with functions?

        The point is that effects and effect handlers are a new form of structured programming, but for effects instead of values. New structure seems heavyweight for trivial things, but ultimately scales and composes better for realistic programs.

        • gsliepen 9 days ago

          > defining C functions and for-loops are so much more verbose than just using JMP instructions in assembly language

          Are you sure? It's not just a JMP; for a loop you need a compare and increment/decrement instruction at the very least, and calling a function is way more complex than a JMP: you have to place the function arguments in the right registers and/or on the right place on the stack, you need to save registers that might get clobbered, and you need to push a return address before you jump. So in C these things are definitely more compact to write.

          I did get the point about effects introducing a new form of structure and composability, and I'd really like to see that. But at the moment it looks like it is as much work as actually implementing a function call in assembler, the only benefit is that the compiler will check the correctness for you.

  • kthielen 9 days ago

    > Just do some reasoning about the side effects.

    "Wat?"

    Have you ever inherited a 1MLoC codebase that you yourself didn't write from scratch, or worked on a large project with at least one other person? How do you know what the side-effects are and where they happen when you aren't intimately familiar with the code you're interacting with? That's the whole point of making effects explicit and available for analysis in the type system.

    • QuadrupleA 9 days ago

      Are you saying you've inherited 1MLoC functional codebases, and due to their shining purity you haven't had to get familiar with them? Or haven't had to understand their "side effects", outputs / effects on the world?

      Side effects are what you care about in a program. The simplest 8-bit CPU has side effects with every single instruction. It's baked into the bedrock, I don't think you can paper it over. Trying to shoehorn the complexity into nothing but function parameters and return values doesn't make the complexity go away, it just necessitates all these other weird contortions that add the complexity back twice over again.

      • mathh 9 days ago

        Yes the good old days of spaghetti code where everything was simpler before it became complicated for me. Let me code my soup of ifs in methods returning void / Unit, there is nothing better, and that these FP lesson givers leave us alone.

        • kthielen 8 days ago

          Ok but just make sure nobody else has to inherit it, and it’ll be fine.

      • kthielen 8 days ago

        Yeah, some maintenance projects have been much easier than others. Implicit knowledge that you have to “just” hunt down is generally the cause of difficulty and delay. It has little to do with “purity” and more to do with not wasting my time.

  • pshirshov 9 days ago

    > its own self-created complexity

    Yes, we use complex tools to avoid writing complex, unpredictable and buggy code.

  • tsss 9 days ago

    Side effect handling also include composable error handling and asynchronous functions. I'm curious to see how you are doing it that is so much better? Forgetting to handle an exception or an asynchronous result is something that probably every person here can relate to.

  • hcarvalhoalves 9 days ago

    Being able to reason, analyze, compose side-effects is important. I think people are still figuring out the right abstractions and ergonomics though - give it sometime. Effect systems are already more familiar than wrestling monad types.

  • kaba0 9 days ago

    With all due respect, you are way too hand-wavy about a topic you don’t want to learn more about. Maybe go at it with an open mind?

  • jayceedenton 9 days ago

    Amen, and if you try to keep pure parts and side-effecting parts separated, the problem of reasoning about side effects is limited to a very small part of your code.

    The pure typed religion and huge weight of theory that goes with it is one reason why I find it so sad that Rust has seemingly won out over Zig.

  • artemonster 9 days ago

    Yeah I always giggle at this style of "dialogue with audience" that many proponents of strange programming gimmicks make:

    "Look, let me demonstrate that this piece of code is clearly VERY bad:

    DoA(); DoB(); DoC();

    Such horrors! What if DoB() does some invisible non-composible side effects of launching full nuclear arsenal of unites states? We clearly need some borrow checking, type checking, monads, continuations and a blessing of a pope to rewrite this horrible, horrible mess!!!!!!!!"

    And then they proceed with a code example that is just a convoluted mess of "what the fuck" and finish with: "look how beautiful and safe and practical this is! industry is stoopid for not using these awesome features!"

    Disclaimer: I tinker with my own PL with algebraic effects and I do think they are useful.

    • pshirshov 9 days ago

      The problem is precisely the fact that you cannot rewrite the mess because you cannot reason about it. Your typical code has way too many aspects and not enough enforced contracts to be maintainable.

      • agumonkey 9 days ago

        I'm very FP friendly, but I think that the mainstream just pays for this defect. They'll have service layers, modules, classes with some side effects sprinkled here and there at every step. And if they don't get it well, they just delay a release to have time to deal with it. I'd rather have cleaner more general way to assemble code in a mathematical manner but I don't see it grow in mainstream software engineering.

K0balt 9 days ago

The very existence and continued interaction with the outside world of the FP community is a fundamental violation of effect purity.

Eventually the entire FP community is going to be engulfed by the event horizon of the zero side effect singularity and disappear completely.

This will be intentional.

  • CoastalCoder 9 days ago

    Wouldn't their academic papers still get converted into Hawking radiation?

    • K0balt 9 days ago

      Oh dear. I guess they will eventually disappear completely then, until FP is reinvented in the next big bang!

hardwaresofton 9 days ago

It's wild that this article only mentioned Haskell in passing when libraries like FreeR, fused-effects, and etc have been been around for a long time, and what people really worry about at this point is how to get mtl (monad transformer library) speeds out of effects systems (and even that was solved IIRC).

Sure it's a scala-focused article but come on -- Haskell is far more ergonomic, and honestly easier on the eyes than Scala.

  • jghn 9 days ago

    The author runs a Scala based consultancy and writes books on Scala. It makes sense that it'd be Scala focused.