←back to thread

157 points matt_d | 1 comments | | HN request time: 0s | source
Show context
kubb ◴[] No.45136229[source]
For people using OCaml, there’s one thing that kinda discourages me in it, that is exceptions as part of the API in the standard library.

Because exceptions aren’t checked, this effectively means that a language designed for type safety has as much type safety as python, because it’s very easy to forget handling something, and get runtime errors.

How do you deal with this day to day? I assume it’s impossible to just believe that all the code you pull in doesn’t use exceptions?

replies(4): >>45136795 #>>45137250 #>>45137299 #>>45142057 #
debugnik ◴[] No.45137250[source]
> as much type safety as python

There's no type unsafety from unchecked exceptions, because uncaught exceptions are not unsound. Even Haskell has them (error and undefined), because from a theoretical standpoint they're equivalent to reaching an infinite loop. (Now, recovering from an exception isn't unsound either, but it might mess with your usual mutable invariants.)

In more practical terms, concerning overall correctness, OCaml has been adding option-returning variants of those functions, so most exceptions raised from the stdlib nowadays are much more likely to be intended by the author.

replies(1): >>45139713 #
ux266478 ◴[] No.45139713[source]
I don't think Haskell is a good language to model our idea of error handling off of. It's one of many bugbears I have with that language, that it uses the Maybe monad as an error type. It technically works, but doesn't provide a meaningful distinction between "This function might not return anything, and this is defined behavior" and "This function has a singularity". MonadError exists, but I can't think of anywhere it shows up without digging deep into dragon caves of the compiler. Everything a normal user is going to touch will deal exclusively in Maybes.

I'm not a fan of Rust as a language for many reasons, but I will give it credit for making proper usage of the Result monad. They could have abused Option the same way Haskell abuses Maybe, but they didn't.

replies(2): >>45140539 #>>45157015 #
1. debugnik ◴[] No.45140539[source]
I was just using Haskell's reputation to push back on the "as much type safety as python" hot take.

> [Haskell] doesn't provide a meaningful distinction between "This function might not return anything, and this is defined behavior" and "This function has a singularity"

I think Haskellers should fear divergence less, or push for SPARK-like static checking. In OCaml, the current trend would be to represent "not return anything" as None; and "has a singularity" by raising Invalid_argument or similar when the singularity check was considered a precondition, or returning Error (or an equivalent variant) for expected inputs.

Usage of Result in OCaml is also growing, thankfully. It's part of the stdlib, and we can use binding operators (let* foo = result) to do the same as ? in Rust (or let! in F#). OCaml 5.4 is even adding a Result.Syntax module so we can just open it instead of defining (let*) ourselves.

On the other hand, Result doesn't give us backtraces, and composes badly with other combinators or imperative flow. In my current project I'm instead giving a try to an effectul result_scope/get_ok API, which composes better.