Hacker News .hnnew | past | comments | ask | show | jobs | submit | uzerfcwn's commentslogin

I don't know what quotemstr was specifically talking about, but here's my own take.

The ideal error handling is inferred algebraic effects like in Koka[1]. This allows you to add a call to an error-throwing function 15 layers down the stack and it's automatically propagated into the type signatures of all functions up the stack (and you can see the inferred effects with a language server or other tooling, similar to Rust's inferred types).

Consider the following Rust functions:

    fn f1() -> Result<(), E1> {...}
    fn f2() -> Result<(), E2> {...}
    fn f3() -> Result<(), E3> {...}
    fn f4() -> Result<(), E4> {f1()?; f2()?;}
    fn f5() -> Result<(), E5> {f1()?; f3()?;}
    fn f6() -> Result<(), E6> {f4()?; f5()?;}
Now, how do you define E4, E5 and E6? The "correct" way is to use sum types, i.e., `enum E4 {E1(E1), E2(E2)}`, `enum E5 {E1(E1), E3(E3)}` and `enum E6 {E1(E1), E2(E2), E3(E3)}` with the appropriate From traits. The problem is that this involves a ton of boilerplate even with thiserror handling some stuff like the From traits.

Since this is such a massive pain, Rust programs tend to instead either define a single error enum type that has all possible errors in the crate, or just use opaque errors like the anyhow crate. The downside is that these approaches lose type information: you no longer know that a function can't return some specific error (unless it returns no errors at all, which is rare), which is ultimately not so different from those languages where you have to guard against bizarre runtime errors.

Worse yet, if f1 has to be changed such that it returns 2 new errors, then you need to go through all error types in the call stack and flatten the new errors manually into E4, E5 and E6. If you don't flatten errors, then you end up rebuilding the call stack in error types, which is a whole different can of worms.

Algebraic effects just handle all of this more conveniently. That said, an effect system like Koka's isn't viable in a systems programming language like Rust, because optimizing user-defined effects is difficult. But you could have a special compiler-blessed effect for exceptions; algebraic checked exceptions, so to speak. Rust already does this with async.

[1] https://koka-lang.github.io


Group theory entering quantum physics is a particularly funny example, because some established physicists at the time really hated the purely academic nature of group theory that made it difficult to learn.[1]

If you include practical applications inside computers and not just the physical reality, then Galois theory is the most often cited example. Galois himself was long dead when people figured out that his mathematical framework was useful for cryptography.

[1] https://hsm.stackexchange.com/questions/170/how-did-group-th...


> When I run 'notepad dir1/file1.txt', the package should not sneakily be able to access dir2.

What happens if the user presses ^O, expecting a file open dialog that could navigate to other directories? Would the dialog be somehow integrated to the OS and run with higher permissions, and then notepad is given permissions to the other directory that the user selects?


Pretty sure that’s how it works on iOS. The app can only access its own sandboxed directory. If it wants anything else, it has to use a system provided file picker that provides a security scoped url for the selected file.


It's also how it works on macOS and even on modern Windows if you are running sandboxed apps.


Yes, UIDocumentPickerViewController is 10+ years old at this point.

There’s also a similar photos picker (PHPicker) which is especially good from 2023 on. Signal uses this for instance.


Thanks for sharing this! Went and changed some keybinds right away.


My favourite feature is userChrome. The default chrome sucks in both Chrome and Firefox, but at least Firefox allows me to customize it to my liking without forking the entire browser.

On the flip side, changing keybinds in Firefox requires forking, but the defaults aren't too bad.


I feel that Windows Registry is similar legacy cruft as environment variables. Worse yet, most software doesn't document which registry keys it's using, so you have to find them on some ancient forum comment or do the detective work by yourself.


> Is there anything C# _doesn’t_ have?

Pi types, existential types and built-in macros to name a few.


Sum types are the ones I really miss. The others would be nice but processing heterogeneous streams is my biggest practical issue.


Last month, a Finnish court judged that using derogatory words in an email sent privately to the offended person counts as defamation.[1] When this was discussed in the Finnish Reddit [2], some found it unjust that it counts as defamation even though the message wasn't sent to third parties, but it is indeed how the law was written.

[1] https://www.iltalehti.fi/kotimaa/a/6c9a65fe-f706-449e-b0d9-1...

[2] https://old.reddit.com/r/Suomi/comments/1mv9usq


The core difference between sums and unions is that sum types have cardinality |A+B| = |A| + |B|, whereas union types have cardinality |A∪B| = |A| + |B| - |A∩B|. As you noted, type systems with union types, such as Typescript, also support sum types because you can create disjoint wrapper types (like Ok and Err) and their union type will be semantically equivalent to a sum type, since the intersection is an empty set. In this sense, union types are strictly more powerful than sum types.

The downside is that union types require some notion of subtyping, since otherwise A∩B is always empty for distinct A and B. Unfortunately, subtyping is apparently very difficult to implement in HM-like type systems (like Rust and ML) such that it plays well with type inference.[0] Hence, the downside of having union types in a language is that users have to write out types more often.

Unlike kibwen, I don't think Rust's type system is particularly essential for new languages. It's a design choice where one side has more powerful types but the other side has more powerful type inference.

[0] https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_sy...


The problem with forking is that updating becomes a nightmare. Most ERPs provide a stable-ish API and heavily recommend customers to stick with it, because then automatic updates just work.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: