Live data from Hacker News

Rust RAII is better than the Haskell bracket pattern

snoyman.com

91–100 of 156 posts

Re: Rust RAII is better than the Haskell bracket pattern

#91
post #35
post #15

Something to keep in mind - linear types are on their way[1], with exactly this usecase in mind. Simon Peyton Jones gave an excellent presentation on the topic[2], briefly discussing exceptions, as well as giving a mention to ResourceT and the phantom type solution in the article (described as channel-passing). [1] https://arxiv.org/abs/1710.09756 [2] https://www.youtube.com/watch?v=t0mhvd3-60Y

Please, don't add them to the language. Use the library approach instead, it is much more Haskellish.

It's extremely difficult to do this and maintain even the figment of usability.

Unless, of course, you're implying it's very haskellish to implement libraries with huge usability gotchas (of which ResourceT was one until the Ghosts of Departed Proofs paper reminded us we can reuse the machinery of ST), then I totally agree.

Re: Rust RAII is better than the Haskell bracket pattern

#93
post #35

Earlier quoted context omitted.

Please, don't add them to the language. Use the library approach instead, it is much more Haskellish.

Is it possible? I mean, to add linear types via a library? I feel like it would have been done already if it were.

It's possible if you have dependent types and are not afraid to (ab)use the type system. See section 2.4 of my thesis (link in bio) for a taste. You have to squint a bit but a system like that can ensure linearity.

Re: Rust RAII is better than the Haskell bracket pattern

#94

Earlier quoted context omitted.

Python's "with" construct is analogous to the bracket pattern in Haskell that the article is talking about. It also works in the nested case in the presence of exceptions. Furthermore, the issue that Michael has with the bracket pattern in Haskell can also happen in Python.

True, but in Python the coding mistake would stand out much more because the with block is syntax sugar - it does not look like regular function application, whereas in the Haskell example there is nothing to tell you that withMyResource is using the 'bracket pattern' (except by reading the src) Also I guess in Haskell there is more expectation that the type system should prevent you from expressing runtime errors

I can see why you might think that, being built into the language, using 'with' in Python in a broken way would be easier to spot. However, having used both languages extensively, I can tell you that, at least for me, there's no discernible difference.

I think the reason for this is might be that, in Haskell, a function starting with 'with' is, by convention, using the bracket pattern and the way that you might use such a function would be very similar in structure to the Python way.

Something that is often said about C++ is that, you're only ever using 10% of the language, but that everyone uses a different 10% and it's true, but it's true of every language to differing degrees. Everyone has their own way of forming programs, just like everyone has their own slightly different style of playing chess, cooking or forming sentences.

When you have a well developed style, you will quickly spot any deviations from it. At that point, it doesn't matter if your style was forced on you by the language or whether it's just a convention that you use.

It's certainly true that Haskellers expect a lot from the type system, even compared to other static languages, let alone Python.

Re: Rust RAII is better than the Haskell bracket pattern

#95
post #35

Earlier quoted context omitted.

Please, don't add them to the language. Use the library approach instead, it is much more Haskellish.

Haskell has such an extensive set of language extensions, I would say adding new features to the type system is probably the MOST Haskell-ish way of doing things. The explicit purpose of Haskell is to be a basis for research into functional language design (edit: among other purposes). By "explicit purpose" I mean exactly that... people got together in 1987 to come up with a language for research. Haskell was never s…

I do normal, boring line-of-business programming in Haskell every day.

I think Haskell does have a good model for bringing together practical application of theoretical research.

Parent's comment is spreading the myth that Haskell is an academic language. It's not wrong but it's not Haskell's only stated purpose or utility by far.

Re: Rust RAII is better than the Haskell bracket pattern

#96
post #10

How do you handle errors at resource release? When you close a file, the final writes take place, and they can fail. What's the idiom in Rust for getting them out? Python's "with" clause, and the way it interacts with exceptions, is the only system I've seen that gets this right for the nested case.

> How do you handle errors at resource release? When you close a file, the final writes take place, and they can fail. What's the idiom in Rust for getting them out? That is unclear. Currently, `File::drop` ignores all errors and drops them on the floor ([unix], [windows]). This is a concern both long-standing and ongoing[0]. AFAIK discussion has gone no further than https://github.com/rust-lang-nursery/api-guideline…

The fact that this is not resolved after over a year is concerning to me. At some point you have to make a decision and implement a solution, even if not everyone agrees 100% on which solution to chose.

Letting this slide for this long is a very bad sign. I’ve been a big Rust fan for my hobby projects, but the whole point of Rust is effortless correctness and safety. The more I encounter bugs and issues that have no near term solution planned, the more confidence I must admit I’m losing in their bug vs feature work prioritization scheme.

For example, it seems sometimes that Rust management would rather focus on cool new language enhancements / rewrite projects, than fix major bugs (sometimes even major borrow checker bugs, or random segfaults created in correct programs).

Re: Rust RAII is better than the Haskell bracket pattern

#97

Earlier quoted context omitted.

> when many C++ and Rust programs are about to end, they spend the last few cycles uselessly deallocating memory that would've immediately been freed via _exit(2) thank god they do this. how many times did I have to manually force linux to release sockets because badly coded C programs which opened sockets forgot to release them causing them to hang up for ~5 minutes after the process ended. With proper RAII classes…

Does _exit wipe out memory or just mark some regions as free ? asking for security purposes.

I don't know how Linux manages its memory pages. FreeBSD would put all of the anonymous pages onto essentially a free, but not zeroed queue. And there's an optional background job to zero the pages and put them in the zeroed queue. When a new page is needed, the clean queue is checked first, otherwise nonzeroed pages are zeroed on demand during allocation. (Zeroing can be theoretically skipped in cases where the kernel knows the full page will be written to before any reads)

Zeroing on exit would be more secure, but significantly slower -- you want to exit quickly, so you can potentially start a replacement program, which would be expected to, at least sometimes, take time to allocate the same amount of memory. If it does allocate the whole amount immediately, it's not necessarily any slower in total time between zeroing at exit or on mapping; but it there's enough time for the pages to get zeroed in the background, that reduces the amount of time waiting for the kernel to do things.

Re: Rust RAII is better than the Haskell bracket pattern

#98
post #75

Earlier quoted context omitted.

Non-lexical lifetimes do not affect something that implements Drop, so the MutexGuard will, by default, last till the end of its lexical scope. You can still call drop on it manually to release it earlier, though.

Huh! Learn something new every day -- so are lifetimes still exactly describing when things get dropped? And anything implementing Drop just doesn't get optimized lifetimes?

Lifetimes and destructors aren't as directly related as it might feel at first. Destructors of course are a thing that happens at runtime, and sometimes the order in which things get destructed has important observable side effects. (Maybe it prints something, or maybe you care about the order locks are released in. Apart from memory safety questions.)

Lifetimes really have no runtime effect at all. They only exist to prove things about the program at compile time. So all the types and function signatures get assembled together, and then a constraint solver gets run over the whole thing. As long as it returns "yes a solution exists", then no ones really cares about the details of the solution. The benefit of non-lexical lifetimes is to weaken the constraints on the system, so that code that used to appear invalid now appears valid. But I believe it will have no effect on any existing code. (There's a Rust compiler reimplementation somewhere that doesn't even check lifetimes, since you can always use the standard compiler in testing.)

Re: Rust RAII is better than the Haskell bracket pattern

#99
post #75

Earlier quoted context omitted.

Non-lexical lifetimes do not affect something that implements Drop, so the MutexGuard will, by default, last till the end of its lexical scope. You can still call drop on it manually to release it earlier, though.

Huh! Learn something new every day -- so are lifetimes still exactly describing when things get dropped? And anything implementing Drop just doesn't get optimized lifetimes?

Not really.

Lifetimes are a language you use to help the compiler prove that all of your references will be valid. If it's unable to prove that, it will throw up an error. That doesn't prove that your references were wrong - it just says that they _might_ be wrong, and the compiler won't allow that possibility. Non-lexical lifetimes just provide the ability to prove more refences and thus allow more code to compile - code that was already fine, but, the compiler couldn't figure out that it was fine.

Re: Rust RAII is better than the Haskell bracket pattern

#100

Earlier quoted context omitted.

> Rust's ownership problem solves it for trivial cases, at the cost of making it hard to do other things Your analysis of the trade offs is fine, but you claim that Rust only solves this problem for "trivial" cases. If that's true, then most of the Rust code I've written is trivial. To me, that pretty thoroughly weakens your dismissal here, at least in my case.

I am talking about just using basic references & borrowing. Once you introduce reference counting (Rc and Arc ) and copying, you open up a lot more options, of course, but at this point you also can't make any lifetime guarantees anymore, because objects can escape the "owner's" scope at will.

Yes but that isn’t a problem because you will still be protected from all the things that rust is trying to protect you from.
Post reply on HN