From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by sympa.inria.fr (Postfix) with ESMTPS id 3B2797EE5B for ; Mon, 26 May 2014 18:02:39 +0200 (CEST) Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of philippe.veber@gmail.com) identity=pra; client-ip=74.125.82.181; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="philippe.veber@gmail.com"; x-sender="philippe.veber@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail3-smtp-sop.national.inria.fr: domain of philippe.veber@gmail.com designates 74.125.82.181 as permitted sender) identity=mailfrom; client-ip=74.125.82.181; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="philippe.veber@gmail.com"; x-sender="philippe.veber@gmail.com"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail3-smtp-sop.national.inria.fr: no sender authenticity information available from domain of postmaster@mail-we0-f181.google.com) identity=helo; client-ip=74.125.82.181; receiver=mail3-smtp-sop.national.inria.fr; envelope-from="philippe.veber@gmail.com"; x-sender="postmaster@mail-we0-f181.google.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AugBAJxkg1NKfVK1lWdsb2JhbABZg1lYrUOUTgGBDAgWDgEBAQEHDQkJEiqCJQEBAQMBEhUZARsdAQMBCwYFCwM4IgERAQUBHAYTIogLAQMJCA2jL2qNGYMNmW4KGScNZIU2EQEBBAyJJ4UbBAeEQASZc5E2GCmEajs X-IPAS-Result: AugBAJxkg1NKfVK1lWdsb2JhbABZg1lYrUOUTgGBDAgWDgEBAQEHDQkJEiqCJQEBAQMBEhUZARsdAQMBCwYFCwM4IgERAQUBHAYTIogLAQMJCA2jL2qNGYMNmW4KGScNZIU2EQEBBAyJJ4UbBAeEQASZc5E2GCmEajs X-IronPort-AV: E=Sophos;i="4.98,913,1392159600"; d="scan'208";a="64199221" Received: from mail-we0-f181.google.com ([74.125.82.181]) by mail3-smtp-sop.national.inria.fr with ESMTP/TLS/RC4-SHA; 26 May 2014 18:02:38 +0200 Received: by mail-we0-f181.google.com with SMTP id w61so8118887wes.26 for ; Mon, 26 May 2014 09:02:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; bh=FNHP9xCF4tLjmIgF57GGpWUCu+bgW79Pp5CiZmKdpio=; b=pIUa2QMav/HH2NpvekxHPC7DO5L+d3pVwIie1Y/eKA1yNvgZlYWii55AFTmip5VOXH ZBbHzauatnrKQzlyMLw+i9n1F/P01BKOq0/agcvSA9mqEK40Fi3Jb+oyaSEaG5EhFkJc PMwEm6qHCW+dovFIaabRYbCtBx7DoQ1sHpsz1hB1nyNbuqsh94AG3GFROa9PelA0xj+F QXCOGhTvtB6BwDzi3LuubDVh3ssLdLsG9Lxf0giAovY6OBY3FOphMVfK1OP8O5pMihhY sFpmuux8OH+Zq+FTr07wFnc2g/YlqJMUlLjZswVNnILMz0exj5ThGorJSt1XCvQhlVAL ZB5g== X-Received: by 10.194.77.72 with SMTP id q8mr28875709wjw.82.1401120155682; Mon, 26 May 2014 09:02:35 -0700 (PDT) MIME-Version: 1.0 Received: by 10.194.239.100 with HTTP; Mon, 26 May 2014 09:02:15 -0700 (PDT) In-Reply-To: References: <53835610.9050609@inria.fr> From: Philippe Veber Date: Mon, 26 May 2014 18:02:15 +0200 Message-ID: To: Ben Millwood Cc: Romain Bardou , caml users Content-Type: multipart/alternative; boundary=047d7bfcebd42ace2304fa4fb584 X-Validation-by: philippe.veber@gmail.com Subject: Re: [Caml-list] Uncaught exceptions in function type. --047d7bfcebd42ace2304fa4fb584 Content-Type: text/plain; charset=ISO-8859-1 Hi Ben, 2014-05-26 17:13 GMT+02:00 Ben Millwood : > First of all, it seems to be universal among all languages I've much > experience with that there are unchecked exceptions. Your program might be > interrupted at any point by an out of memory error or a signal or > something, and there's just not much you can do about that. You can either > model it in your code or not, but you can't stop it from happening. So it > seems like the best we can hope for with typed exceptions is in addition to > unchecked ones, to make it possible (but not required) that a function > might declare some of the exceptions it can throw. > That's perfectly right. > > But after all exceptions are just "things I can return instead of a > result", and lightweight sum types are already pretty good at that. E.g. > (to use Romain's syntax) > > val lookup : map -> key -> value raise Not_found > > is pretty much just the same as: > > val lookup : map -> key -> value option > Right. This is a very good use case that I adopted thanks to core. > > True, exceptions get automatic propagation, but the option monad interface > makes that pretty lightweight, and you can do a similar thing with a less > trivial sum type if you need richer type information. > Using options or Result from time to time is certainly a nice habit. However to be honest, using option/result monads extensively does not seem right to me, like pulling the language in a direction it was not really designed for. Monad combinators do a great job at propagating errors, but still there is a serious addition of plumbing in function body's and Result returning functions have a significantly less readable type. But I guess this is pretty much a question of taste/habit to see if the added verbosity is worth it. > > See also: > https://blogs.janestreet.com/how-to-fail-introducing-or-error-dot-t/ for > discussions of more ways you can make error handling both explicit and > concise. > Thanks! BTW core still uses exceptions. Is there an explicit rule as to how to decide between Result type or exceptions. For instance, why not write the Array.create function like this: val create : int -> 'a -> 'a array Or_error.t where create fails for a negative integer? --047d7bfcebd42ace2304fa4fb584 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable

Hi Ben,

2014-05-26 17:13 GMT+02:00 Ben Millwood = <bmillwood= @janestreet.com>:
First of all, it seems to b= e universal among all languages I've much experience with that there ar= e unchecked exceptions. Your program might be interrupted at any point by a= n out of memory error or a signal or something, and there's just not mu= ch you can do about that. You can either model it in your code or not, but = you can't stop it from happening. So it seems like the best we can hope= for with typed exceptions is in addition to unchecked ones, to make it pos= sible (but not required) that a function might declare some of the exceptio= ns it can throw.

That's perfectly right.
=A0

But after all exceptions are just "things I can re= turn instead of a result", and lightweight sum types are already prett= y good at that. E.g. (to use Romain's syntax)

=A0=A0= =A0 val lookup : map -> key -> value raise Not_found

is pretty much just the same as:

=A0=A0=A0= val lookup : map -> key -> value option
=

Right. This is a very good use case that I adopted thanks to core.=
=A0

True, exceptions get automatic propagation, but the option monad inte= rface makes that pretty lightweight, and you can do a similar thing with a = less trivial sum type if you need richer type information.

Using options or Result from t= ime to time is certainly a nice habit. However to be honest, using option/r= esult monads extensively does not seem right to me, like pulling the langua= ge in a direction it was not really designed for. Monad combinators do a gr= eat job at propagating errors, but still there is a serious addition of plu= mbing in function body's and Result returning functions have a signific= antly less readable type. But I guess this is pretty much a question of tas= te/habit to see if the added verbosity is worth it.
=A0

See also: https://blogs.janestreet.c= om/how-to-fail-introducing-or-error-dot-t/ for discussions of more ways= you can make error handling both explicit and concise.

Thanks! BTW core st= ill uses exceptions. Is there an explicit rule as to how to decide between = Result type or exceptions. For instance, why not write the Array.create fun= ction like this:

val create : int -> 'a -> &#= 39;a array Or_error.t

where create = fails for a negative integer?
--047d7bfcebd42ace2304fa4fb584--