I have respect for Haskell because I saw it long before I saw Rust, and I love the ideas, but I never got around to actually using Haskell.
I think an IO monad and linear types [1] would do a lot for me in a Rust-like
[1] Affine types? Linear types? The ones where the compiler does not insert a destructor but requires you to consume every non-POD value. As someone with no understanding of language theory, I think this would simplify error handling and the async Drop problem
I can understand why Rust didn't implement an IO monad (even though I'd love it), but linear types seem like they would fit right in with the rest of Rust. Not sure why they didn't include them.
There's actually two different ways that Rust types can always be discarded: mem::forget and mem::drop. Making mem::forget unsafe for some types would be very useful, but difficult to implement without breaking existing code [1].
Btw, you are correct with linear types - Affine types allow discarding (like Rust already does).
I think if one implemented linear types in Rust they could still be forgotten, but not. Basically you would have constraints like:
* creating type &T or &mut T is forbidden; therefore also applying & and &mut to a value of linear type, or using ref and ref mut at the top level of patterns that match a value with linear type
* field access is forbidden, except through pattern matching (either match or let) because pattern matching consumes the matched value
* implementing Copy or Drop is not allowed (Copy makes no sense, with Drop using destructuring patterns would not be possible). Well, Drop would not be implementable anyway, together with many other traits, because it takes &mut self (which is not creatable).
I would have no idea how to express it in the syntax.
I used Haskell for a while and eventually switched over (and intentionally target Rust for many new projects, though I suspect I should be doing more Go for really simple things that just don't need more thought).
One large problem with Haskell that pushes people to Rust is strictness, I think -- laziness is a feature of Haskell and is basically the opposite direction from where Rust shines (and what one would want out of a systems language). It's an amazing feature, but it makes writing performant code more difficult than it has to be. There are ways around it, but they're somewhat painful.
Oh there's also the interesting problem of bottom types and unsafety in the std library. This is a HUGE cause of consternation in Haskell, and the ecosystem suffers from it (some people want to burn it all down and do it "right", some want stability) -- Rust basically benefited from starting later, and just making tons of correct decisions the first time (and doing all the big changes before 1.0).
That said, Haskell's runtime system is great, and it's threading + concurrency models are excellent. They're just not as efficient as Rust's (obviously) -- the idea of zero cost abstractions is another really amazing feature.
> [1] Affine types? Linear types? The ones where the compiler does not insert a destructor but requires you to consume every non-POD value. As someone with no understanding of language theory, I think this would simplify error handling and the async Drop problem
Yeah, the problem is that Affine types and Linear types are actually not the same thing. Wiki is pretty good here (I assume you meant to link to this):
Affine is a weakening of Linear types, but the bigger problem here is that Haskell has a runtime system -- it just lives in a different solution-world from Rust.
For rust, Affine types are just a part of the way they handle aliasing and enable a GC-free language. Haskell has the feature almost... because it's cool/powerful. Yes, it's certainly useful in Haskell, but Haskell just doesn't seem as focused on such a specific goal, which makes sense because it's a very research driven language. It has the best types (and is the most widely adopted ML lang IIRC) because it focuses on being correct and powerful, but the ties to the ties to practicality are not necessarily the first or second thought.
It's really something that Rust was able to add something that was novel and useful that Haskell didn't have -- obvious huge credit to the people involved in Rust over the years and the voices in the ecosystem.
I think an IO monad and linear types [1] would do a lot for me in a Rust-like
[1] Affine types? Linear types? The ones where the compiler does not insert a destructor but requires you to consume every non-POD value. As someone with no understanding of language theory, I think this would simplify error handling and the async Drop problem