On the other hand, the lack of 'finally' itself is not such a big issue, considering that you are going to end up using either Lwt or Core.Async as soon as you start doing something non-trivial with IO.
On the other hand, the lack of 'finally' itself is not such a big issue, considering that you are going to end up using either Lwt or Core.Async as soon as you start doing something non-trivial with IO.
https://github.com/mirage/mirage/blob/master/types/V1.mli#L2...
type error = [
| `Unknown of string (** an undiagnosed error *)
| `Unimplemented (** operation not yet implemented in the code *)
| `Is_read_only (** you cannot write to a read/only instance *)
| `Disconnected (** the device has been previously disconnected *)
]
val read: t -> int64 -> page_aligned_buffer list ->
[ `Error of error | `Ok of unit ] io
This lets the larger scale module assembly fit together with explicit checking that each device driver connected and initialised ok, and is the equivalent of basic checked exceptions. Completely checked exceptions are something of a pain to work with...It's OK, but it's a lot like the old "programmers with enough discipline can use footguns safely" argument.
This works pretty well in practise, and is quite similar to Erlang's monitor model. It's verbose and undesirable to handle _all_ exceptional cases in a distributed system explicitly via checked exceptions, and using monitors to catch exceptions that we're not expecting and do a process kill/log/restart is a good model in my mind.
OCaml gives the language flexibility to migrate to this as well, which is nice (since, as you note, we'll never get all the third-party code we depend on to be exception-free, and nor do I think that is a desirable goal). Core and Async from Jane Street also exhibit this split: Core tends to use On_error to explicitly handle errors, and Async (being used for distributed programming) instead adopts a "raise-exception-and-catch-it-in-a-monitor" model. Theres more on that in the Async chapter in RWO: https://realworldocaml.org/v1/en/html/concurrent-programming...
However, people generally use various "with" functions to manage resources. That's better than try..finally because the allocation can't get separated from the try bit.
I never found Java checked exceptions much use for resource leaks, since unchecked exceptions are always still possible.
That's what I wanted to say, but reading back, it was a bit unclear. Though I'd recommend lwt.ppx over its camlp4 ancestor...
> However, people generally use various "with" functions to manage resources.
Which I assume are usually implemented via try/finally if using Lwt :)
> I never found Java checked exceptions much use for resource leaks, since unchecked exceptions are always still possible.
It's not fool-proof, but having a codebase where most exceptions are checked exceptions still protects you in many cases. And of course, try-with-resource is a good way to guarantee against resource leaks in the majority of cases.