I've been writing some Haskell again the past couple days, and something that has struck me is how much I miss move-semantics. Like, I'm not complaining about it being garbage collected, that's great and makes a lot of things easier.
No what I'm talking about is being able to easily express concepts like "Whatever value you pass into this function, you can't use it anymore after you pass it in! But you can have this other return value derived from it"
Like for example say I had a queue of work waiting to be executed. I want to write a function that at a high level expresses "if there's a job that can be run right now, remove it from the queue and give it to me, otherwise leave the queue unchanged and give me Nothing".
In rust- well in idiomatic rust you'd probably take a mut reference to the queue, take the element out, return that element or None- But imagine we were using rust with immutable datastructures like some kinda weirdo. I could write a function like this:
fn popNextRunnable(queue: WorkQueue) -> (Option<Job>, WorkQueue) {
// do something here
}
Notice I didn't take queue by reference, I took it by value. That means the rust compiler knows that the queue is getting moved into the function and can never be used again! It disappears off into the void forever! But you get a new WorkQueue back to replace it, don't worry, and maybe you get a Job to run too.
Well it turns out this is called Affine Types, which is related to Linear Types (there's a cool chart on wikipedia/Structural type system). And I'm hooked.
There's not really a good way to express this in haskell to my knowledge, you kinda just have to document "hey please don't pass the original workqueue around anymore afterwards ok? it won't be meaningful to anyone". And you could corral yourself into the right behavior with the State transformer, but like, still nothing stops you from holding onto the old state. Maybe someone has hacked something together though, never bet against a haskell type-system programmer.
It looks like Haskell 9.0.1 landed an experimental extension for linear types, and that's pretty cool. I think I could write some of the things I want with this, once it's not experimental.
But the thing that's funny to me about all this is I didn't even know I was learning how to use linear/affine types. I just, learned them, as a consequence of learning how to use Rust. But now I get it. Now I get why they're useful and DANGIT now I want them available everywhere!