News for hackers. Stuff that matters.
Re:Exotic Programming Ideas, Part 3: Effect Systems by lambda_obrien on Sunday November 22, 2020 @12:56PM (#25179424)
An effects system like this is more about controlling your own code and allowing for switching off implementations easily versus declaring what effects it has. Your declaration of effects on your function is saying, for example, "I need to output some text," and then in the caller of that function you have to do some action to "consume" that effect. For instance, your example might be an effect called "WriteState" and then you could call that function in a small unit test with a thin layer over a Map, in dev you could call it with a local sqlite db, and in prod you'd call it with your postgres or whatever. Each implementation shares a common interface, but does something different with the data. If you were writing a library, you'd give your public API as the base monad of your library, or as IO maybe, or even give a pure API. You should be dealing with the possible failures under that base context and then the user doesn't need to know about the inner failures.

The effects system effectively acts as an abstraction for some side effect, like an interface, and gets ride of a lot of the boilerplate code needed for mtl or custom transformer stacks.

Also, in strict typing it's pretty easy to refactor with modern linters and such, it actually makes refactoring an API change delightfully simple, just get rid of the red squiggle lines telling you you types are wrong.

Re:Exotic Programming Ideas, Part 3: Effect Systems by skybrian on Sunday November 22, 2020 @03:57PM (#25181022)
Refactoring tools are nice so long as you are in a closed-world environment where you can see all the code and make whatever changes are needed. They don't help nearly as much in an open environment where there are many code owners and not all code is visible to you. When you publish a library, a refactoring tool isn't going to tell you everyone who uses your library, and you don't have permission to change the call sites anyway.

The only thing for it is to push a new, incompatible version and other people will have to migrate. So you're pushing off the work onto them.

I don't see how an effects system helps with this much? It might help you better understand how you painted yourself in a corner, but I don't see how it helps you get out of it.

Re:Exotic Programming Ideas, Part 3: Effect Systems by Quekid5 on Sunday November 22, 2020 @04:13PM (#25181166)
I mean... if you're fixing a broken API, you're going to have to bite the bullet either way -- papering over it isn't going to fix anything... it just hides the problems.

With a type system which understands effects, at least the compiler can give you very accurate help in fixing call sites.

Re:Exotic Programming Ideas, Part 3: Effect Systems by skybrian on Sunday November 22, 2020 @05:31PM (#25181736)
It does help by telling you what's wrong. But in a way, increased precision makes the problem worse.

Suppose you have have a language with two categories of functions, those that can fail (returning an error) and those that can't.

It's nice that within the "functions that can fail" category, you don't have to worry about what kind of error it might be. Error propagation can happen in a generic way. Adding a new kind of error doesn't change any API's.

If instead, you have different kinds of errors and declare them everywhere, you end up with a situation like Java's checked exceptions. The problem is being too precise, which doesn't leave room for changes later.

Similarly, we could be very generic about effects. Maybe we could just say "this function has effects" and treat them all the same? By not being precise about what the effects might be, we aren't promising too much, so we allow ourselves room for change.

The downside is that the caller has to assume any effect is possible. This is a fundamental tradeoff between caller and callee convenience. You need to be specific enough for the caller to be able to deal effectively with the effects you declare, but not too specific, or you're painting yourself in a corner.

Re:Exotic Programming Ideas, Part 3: Effect Systems by lambda_obrien on Sunday November 22, 2020 @08:03PM (#25182576)
Honestly, in the Haskell world, no one really complains about broken APIs, it's actually pretty common for a library to change things in a breaking way. People tend to either use Nix or stack to deal with versioning or they just plan to refactor when they have to. I personally just started with Haskell, but I've switched a small tool from one streaming library to another and it was super easy even though each had a very different API.

Also, breaking API changes happen in every language, on every codebase, ask the time. At least with static types and a common linter I can refactor and be a hundred percent sure it works since it compiles, whereas in Python for example I can't be sure unless I add tests and stuff, even then...

Re:Exotic Programming Ideas, Part 3: Effect Systems by Chris_Newton on Monday November 23, 2020 @01:56PM (#25190227)
Honestly, in the Haskell world, no one really complains about broken APIs

I don’t believe that’s true. The very existence of Stack and Stackage is testament to how significant the compatibility problems had become in the Haskell ecosystem.

Even if it were true, Haskell world is tiny and (in)famously has the motto “Avoid success at all costs”, so it isn’t necessarily a representative example of practices that would be effective in other contexts.

The advantage with a type system as explicit as Haskell’s is that at least if there is a breaking change in an interface you depend on, you get quite good information about where the problem is and what you need to do to fix it.

Also, breaking API changes happen in every language, on every codebase, ask the time.

Some people take backwards compatibility extremely seriously, and code that depends on their interfaces still works just fine many years after it was written. The pace of development is usually slower when robust standardisation is part of the process, but that isn’t necessarily a bad thing given the stability you get in return.

At least with static types and a common linter I can refactor and be a hundred percent sure it works since it compiles

This is a common claim in the Haskell world, but of course it’s not really true. It always reminds me of Knuth’s famous quip, “Beware of bugs in the above code; I have only proved it correct, not tried it.”

Re:Exotic Programming Ideas, Part 3: Effect Systems by skybrian on Sunday November 22, 2020 @09:09PM (#25182929)
Yes, there are easier and harder ways to deal with api migrations. But even in Haskell, isn't "Cabal hell" a thing? And the type of the standard prelude's head function is wrong but it can never be changed.

Dependency migration is the sort of thing that's easy enough in small examples and gets harder as you scale up.

Re:Exotic Programming Ideas, Part 3: Effect Systems by Quekid5 on Friday November 27, 2020 @03:11PM (#25232181)
> But even in Haskell, isn't "Cabal hell" a thing?

No. Just use stack + Stackage and you have a huge set of packages which are mutually compatible.

(You can also use cabal-install with a Stackage snapshot, I think. Not sure though. Cabal-install has also improved massively and doesn't really do "global" installation of dependencies, so it'll help a lot... but you may still run into difficulties making different versions of your project's dependencies work together.)

Re:Exotic Programming Ideas, Part 3: Effect Systems by Chris_Newton on Monday November 23, 2020 @02:01PM (#25190301)
But even in Haskell, isn't "Cabal hell" a thing?

Less so than it used to be. Cabal received a big update a few years ago, and the new-style commands now operate more like many other package managers in terms of isolation etc.

Re:Exotic Programming Ideas, Part 3: Effect Systems by lambda_obrien on Monday November 23, 2020 @02:31AM (#25184367)
You should use Haskell and see what it can do, you can change the prelude easily, for instance.

The standard head function is partial, yes, but that's not a big deal at all.