Live data from Hacker News

Rust vs. Haskell

serokell.io

151–160 of 189 posts

Re: Rust vs. Haskell

#151

Would not a better comparison be Ocaml vs Rust? In the end Rust WAS written in OCaml, and is heavily influenced by it.

Early alpha/beta rust docs mentioned Haskell all the time as a point of comparison, but I don't recall them ever mentioning OCaml.

Also, Rust's idiomatic type system usage is way closer to Haskell's than it is to OCaml's (with typeclasses, no polymorphic variants, no module functorization, etc.)

Re: Rust vs. Haskell

#152
post #134

Earlier quoted context omitted.

That's not just closures, but a confluence of closures, async, and more.

The example provided in the post -- yes. But I can basically demonstrate other language features that are not working with closures, such as generics -- you just can't have generic closures in the same way as you have generic functions, even in a synchronous code. With closures, you have a pretty limited scope of what you can do, considering the rest of the language, so I think it'd be pretty useless to consider clos…

> But I can basically demonstrate other language features that are not working with closures, such as generics -- you just can't have generic closures in the same way as you have generic functions, even in a synchronous code.

Generics and closures work just fine:

    use std::ops::Add;

    fn adder + 'static>(x: T) -> impl Fn(T) -> Box T> {
        move |y| Box::new(move |z| y + x + z)
    }

    fn main() {
        let add23 = adder(2)(3);
        assert_eq!(10, add23(5));
        assert_eq!(13, add23(8));
    }
You keep making sensationalist generalizations. It's trivial to demonstrate that closures and generics work together just fine, as I've done above. Are there subtleties and complexities and other things that can make certain cases or areas tricky? Absolutely. But that's not the same as "not working."

Re: Rust vs. Haskell

#153

This article paints Rust and Haskell as very similar languages, but when I saw the title I was thinking about how they are fundamentally different. Rust is technical and exposes/requires you to understand the reality of computation, while Haskell hides it away and lets you program in a system based on lambda-calculus (you don't even have strict order of evaluation!) Interesting to see that they are very similar regar…

Quite a few of Rust's features were borrowed from or inspired by ones in Haskell - albeit often modified to be more suitable for systems programming (and systems programmers!). Most Haskellers I know are quite fond of Rust :)

I am (or used to be) a Haskeller, and I just can’t get over how spectacularly ugly Rust’s syntax looks compared to Haskell or SML and finally force myself to learn it. Call me shallow, but it’s true.

Re: Rust vs. Haskell

#154
post #94

Earlier quoted context omitted.

If given explicit support in a language then no it's not. Especially with the keyword approach rust is taking, the compiler will guarantee the semantics. Do you believe the exec system call is similarly unreliable at replacing your process image? Amazing that unix systems work at all

> If given explicit support in a language then no it's not. Especially with the keyword approach rust is taking, the compiler will guarantee the semantics. Then it's TCE not TCO. > Do you believe the exec system call is similarly unreliable at replacing your process image? Exec is entirely unlike TCO. If exec was a syscall which sometimes did and sometimes did not replace your process image, then it'd be like TCO, an…

I think it would have helped if you'd defined your terms earlier. Wikipedia, for example, doesn't distinguish between the terminology TCO and TCE: https://en.wikipedia.org/wiki/Tail_call

Re: Rust vs. Haskell

#155
post #136
post #22

About Haskell's function type annotations: "But it usually results in a warning, and adding a type signature is a good practice." I prefer Rust's way of doing this. When you're a beginner it ensures that you're passing and returning the proper type to and from the function, you kind of have the function as a guard which ensures that you're using the correct types.

Rust only half-asses this though. Lifetime annotations are part of the type of the function but can be elided if unambiguous. For beginners and generally people who read code that's confusing. I don't think there's anything to be gained by writing a few less characters and editors can easily add them as well.

There's crucial nuance here.

Lifetime annotations aren't elided based on there being only one unambiguous answer. Rather, there's three simple rules[1] that look at the function signature and in simple cases give what you probably want. If those simple rules don't match your use case you need to define manually, the compiler doesn't get clever.

This means that if you want to take a reference to an array and return a reference to an item in an array, for example, elision will work fine. But if you take a reference to a key and look up a reference to the value in a global map you need to write it by hand, even though the compiler could pretty clearly guess the output lifetime you want.

This preserves a crucial feature: you can know the exact signature of a function by only looking at the signature definition, you don't need to look into the body.

Lifetime elision isn't like inferring argument types. It's like defaulting integer literals to i32 unless you specify otherwise.

See https://doc.rust-lang.org/nomicon/lifetime-elision.html

Re: Rust vs. Haskell

#156
post #78

Earlier quoted context omitted.

You don't need to know that to write haskell Effect systems and monad transformers are advanced topics. They're possible to use in my language yet most people do not and can still write software. Certainly no need for them in Haskell to be successful. You can just program at the lower levels of abstraction common in other languages. The only difference is that Haskell's community tends to emphasize abstraction

There's no way to even get a job without understanding monad transformers.

If true that's sad and hopefully effectful will bring than to an end https://github.com/haskell-effectful

Re: Rust vs. Haskell

#157

Earlier quoted context omitted.

The example provided in the post -- yes. But I can basically demonstrate other language features that are not working with closures, such as generics -- you just can't have generic closures in the same way as you have generic functions, even in a synchronous code. With closures, you have a pretty limited scope of what you can do, considering the rest of the language, so I think it'd be pretty useless to consider clos…

> But I can basically demonstrate other language features that are not working with closures, such as generics -- you just can't have generic closures in the same way as you have generic functions, even in a synchronous code. Generics and closures work just fine: use std::ops::Add; fn adder + 'static>(x: T) -> impl Fn(T) -> Box T> { move |y| Box::new(move |z| y + x + z) } fn main() { let add23 = adder(2)(3); assert_e…

Well, your example is not a generic closure, since inside `adder`, you already have a generic type `T`; it's introduced by the `fn` keyword. If we try to do the same for a closure, we would face a type error. This issue has been discussed on SO [1].

I haven't claimed that closures are not working, since well, they are working, but under a very limited set of circumstances. Again, I see nothing sensational, since the trickery of using closures has been discussed elsewhere.

[1] https://stackoverflow.com/questions/34814423/possible-to-def...

Re: Rust vs. Haskell

#158

Earlier quoted context omitted.

Being easier than C++ or Haskell isn't really saying much at all. Neither of them have improved code readability and are notorious for their learning curve.

It is saying a lot because no other language offers that combination of performance and high level abstraction. The speed of C++ with high level language features of haskell. And none of the safety pitfalls of C++ either. That's a lot. When compared with haskell the benefits aren't clear. When compared with C++, rust is clearly better when viewed from strictly a language standpoint.

But C++ is an outlier in systems software. Systemd is written in C. Grub is written in C. The Linux kernel is written in C. Firmware is written in C. Sure there are some kernels that use a bit of C++, but it's an outlier, not the norm. C++ never proved the is was so worthwhile to have a higher level language that we should drop everything and write C++. C++ only dominates in performance critical applications where there is a bridge to higher level languages and you're interfacing with software.

The strongest argument for Rust is its safety features. Abstractions have made C++ an unusable mess that even C++ developers complain about on a constant basis.

Re: Rust vs. Haskell

#159

Earlier quoted context omitted.

> "Worthless" is a bit strong. No, TCO is worthless, it’s an unreliable optimisation.

Compiler optimizations are best-effort. -O3 gets you 90% of the optimization for 10% of the work of writing hand-rolled assembly. Individual optimizations are not guaranteed, and sometimes even regress in newer compiler versions, but everyone uses them because overall programs run much faster with optimizations than without. I don't see how TCO is any different. Would you say all optimizations are worthless because t…

> Would you say all optimizations are worthless because they're not guaranteed?

Context is relevant, the context here is language semantics, not things going faster.

TCO is fine to make things go faster, like inlining, unrolling, LICM, ....

TCO is hot garbage when you rely on it for program correctness.

Re: Rust vs. Haskell

#160

Earlier quoted context omitted.

> But I can basically demonstrate other language features that are not working with closures, such as generics -- you just can't have generic closures in the same way as you have generic functions, even in a synchronous code. Generics and closures work just fine: use std::ops::Add; fn adder + 'static>(x: T) -> impl Fn(T) -> Box T> { move |y| Box::new(move |z| y + x + z) } fn main() { let add23 = adder(2)(3); assert_e…

Well, your example is not a generic closure, since inside `adder`, you already have a generic type `T`; it's introduced by the `fn` keyword. If we try to do the same for a closure, we would face a type error. This issue has been discussed on SO [1]. I haven't claimed that closures are not working, since well, they are working, but under a very limited set of circumstances. Again, I see nothing sensational, since the…

> Well, your example is not a generic closure, since inside `adder`, you already have a generic type `T`; it's introduced by the `fn` keyword. If we try to do the same for a closure, we would face a type error. This issue has been discussed on SO [1].

Of course it's generic. If you were to write the type out for the closure, it would be generic over 'T'. (Whether that type ever actually gets written out that way or not is a different matter.) As far as I can tell, what you're saying is that Rust doesn't support higher-rank polymorphism. Which is true (for types, but not for lifetimes). But that's not the same as "generics don't work with closures."

> I haven't claimed that closures are not working

You've said:

> Closures in Rust are fundamentally broken.

(which was completely unqualified and not to a "very limited set of circumstances")

and (emphasis mine)

> But I can basically demonstrate other language features that are not working with closures, such as generics

Post reply on HN