caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] What if exn was not an open type?
@ 2017-10-20  9:56 Malcolm Matalka
  2017-10-20 10:55 ` David Allsopp
  2017-10-21 21:28 ` Nathan Moreau
  0 siblings, 2 replies; 44+ messages in thread
From: Malcolm Matalka @ 2017-10-20  9:56 UTC (permalink / raw)
  To: caml-list

I have a question in two parts:

1. Would this be a good idea? Why? (I'll describe why I think it is)

2. If it were a good idea, is it feasible to do?

Full question:

Despite exceptions being a part of the language, there is a trend in
many libraries to try to avoid using them.  While I cannot find it, I
recall someone (Daniel maybe?) saying that the standard API advice is
that exceptions should not cross API boundaries.

The short reason for why people seem to want to avoid exceptions (which
I agree with) is that they side step the type system for helping you
understand if your code is correct and handles all situations the code
might experience.  Since the exn type is open, it means that one can add
any exception they want so it's not even known what exceptions you might
get ahead of time.

Another aspect of exceptions, which might be more of my personal
experience, is that exceptions tend to be pretty useless after the
fact.  For example, forgetting to handle a Not_found exception is an
exercise in pain.  Maybe I'm just bad at this, but many exceptions just
aren't that useful.  End_of_file is another one that, IMO, makes the
program flow pretty awkward and if you have multiple files you're
reading from at the same time quite ugly.  I tend to use wrappers that
give me an option based API.  Maybe I just bad at solving these problems
though and I'm the problem.

The consequence of this is that even though I put a lot of effort in my
code trying to avoid exceptions, I can never actually know that I have
succeeded unless I'm very defensive and wrap all foreign calls in some
exception handling code.  There are APIs for this, but if I mess up then
I'm in a bad spot.

My proposal is that exceptions becomes a closed type and they reflect
what Java calls "errors", which are things your program logic should
generally not handle but can choose to if it wants to (I think we call
these failures in Ocaml).  The two specific exceptions I can think if
that should exist are: Assertion_failure and Out of Memory.  Another one
that I think might be nice but is open for debate is a
Not_implemented_failure, I use something like this often while building
a system.  I'm sure there are a few more that people can think of are
meaningful, but the point is these represent pretty bad situations that
the program logic shouldn't handle except in special situations.

Thanks for reading,
/Malcolm

^ permalink raw reply	[flat|nested] 44+ messages in thread

* RE: [Caml-list] What if exn was not an open type?
  2017-10-20  9:56 [Caml-list] What if exn was not an open type? Malcolm Matalka
@ 2017-10-20 10:55 ` David Allsopp
  2017-10-20 11:21   ` Ivan Gotovchits
  2017-10-20 17:07   ` Malcolm Matalka
  2017-10-21 21:28 ` Nathan Moreau
  1 sibling, 2 replies; 44+ messages in thread
From: David Allsopp @ 2017-10-20 10:55 UTC (permalink / raw)
  To: Malcolm Matalka, caml-list

Malcolm Matalka wrote:
> I have a question in two parts:
> 
> 1. Would this be a good idea? Why? (I'll describe why I think it is)
> 
> 2. If it were a good idea, is it feasible to do?
> 
> Full question:
> 
> Despite exceptions being a part of the language, there is a trend in
> many libraries to try to avoid using them.  While I cannot find it, I
> recall someone (Daniel maybe?) saying that the standard API advice is
> that exceptions should not cross API boundaries.
> 
> The short reason for why people seem to want to avoid exceptions (which
> I agree with) is that they side step the type system for helping you
> understand if your code is correct and handles all situations the code
> might experience.  Since the exn type is open, it means that one can
> add any exception they want so it's not even known what exceptions you
> might get ahead of time.
> 
> Another aspect of exceptions, which might be more of my personal
> experience, is that exceptions tend to be pretty useless after the
> fact.  For example, forgetting to handle a Not_found exception is an
> exercise in pain.  Maybe I'm just bad at this, but many exceptions just
> aren't that useful.  End_of_file is another one that, IMO, makes the
> program flow pretty awkward and if you have multiple files you're
> reading from at the same time quite ugly.  I tend to use wrappers that
> give me an option based API.  Maybe I just bad at solving these
> problems though and I'm the problem.
> 
> The consequence of this is that even though I put a lot of effort in my
> code trying to avoid exceptions, I can never actually know that I have
> succeeded unless I'm very defensive and wrap all foreign calls in some
> exception handling code.  There are APIs for this, but if I mess up
> then I'm in a bad spot.
> 
> My proposal is that exceptions becomes a closed type and they reflect
> what Java calls "errors", which are things your program logic should
> generally not handle but can choose to if it wants to (I think we call
> these failures in Ocaml).  The two specific exceptions I can think if
> that should exist are: Assertion_failure and Out of Memory.  Another
> one that I think might be nice but is open for debate is a
> Not_implemented_failure, I use something like this often while building
> a system.  I'm sure there are a few more that people can think of are
> meaningful, but the point is these represent pretty bad situations that
> the program logic shouldn't handle except in special situations.

Without wishing to open old debating wounds too much, the argument of exceptions as errors tends to come down as to whether the thing signalled by an exception is truly exceptional. Not_found, for example, in some scenarios is as unexpected or impossible as Invalid_argument. Historically, they're (ab)used for performance reasons, but some of the overhead of that is being addressed in flambda. Note that for some arguable design mistakes - e.g. End_of_file, you can use exception matching to get around this, e.g.

match input_line ch with
| data -> ...
| exception End_of_file -> ...

which means that the old pattern

let data = try Some (input_line ch) with End_of_file -> None

is only needed if you need to compile with OCaml < 4.02

If you haven't come across it, https://caml.inria.fr/pub/old_caml_site/ocamlexc/ocamlexc.htm is an interesting piece of older research around dealing with handling exceptions.

What your proposal does overlook slightly is the use of exceptions for actual flow control. See for example, an oldish post of Alain Frisch's at https://www.lexifi.com/blog/static-exceptions. However, uses of exceptions like this may at some point be subsumed by Algebraic Effects which are being worked on by various people, mostly with multicore OCaml in mind. There's lots of links to that in https://github.com/ocamllabs/ocaml-multicore/wiki as well as other literature elsewhere online.

HTH,


David 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* RE: [Caml-list] What if exn was not an open type?
  2017-10-20 10:55 ` David Allsopp
@ 2017-10-20 11:21   ` Ivan Gotovchits
  2017-10-20 11:38     ` Simon Cruanes
  2017-10-20 17:07   ` Malcolm Matalka
  1 sibling, 1 reply; 44+ messages in thread
From: Ivan Gotovchits @ 2017-10-20 11:21 UTC (permalink / raw)
  To: David Allsopp; +Cc: caml-list, Malcolm Matalka

[-- Attachment #1: Type: text/plain, Size: 4810 bytes --]

It's also a question of efficiency, signaling an absence of data with an
exception is usually more efficient, than signaling the presence of data by
wrapping it in some data constructor, as the latter needs an allocation.
Thus a function that raised an exception is more basic, than a function
that returns an optional value, as the former can be translated into the
latter, but not vice versa if you take an allocation into account.

On Oct 20, 2017 6:55 AM, "David Allsopp" <dra-news@metastack.com> wrote:

> Malcolm Matalka wrote:
> > I have a question in two parts:
> >
> > 1. Would this be a good idea? Why? (I'll describe why I think it is)
> >
> > 2. If it were a good idea, is it feasible to do?
> >
> > Full question:
> >
> > Despite exceptions being a part of the language, there is a trend in
> > many libraries to try to avoid using them.  While I cannot find it, I
> > recall someone (Daniel maybe?) saying that the standard API advice is
> > that exceptions should not cross API boundaries.
> >
> > The short reason for why people seem to want to avoid exceptions (which
> > I agree with) is that they side step the type system for helping you
> > understand if your code is correct and handles all situations the code
> > might experience.  Since the exn type is open, it means that one can
> > add any exception they want so it's not even known what exceptions you
> > might get ahead of time.
> >
> > Another aspect of exceptions, which might be more of my personal
> > experience, is that exceptions tend to be pretty useless after the
> > fact.  For example, forgetting to handle a Not_found exception is an
> > exercise in pain.  Maybe I'm just bad at this, but many exceptions just
> > aren't that useful.  End_of_file is another one that, IMO, makes the
> > program flow pretty awkward and if you have multiple files you're
> > reading from at the same time quite ugly.  I tend to use wrappers that
> > give me an option based API.  Maybe I just bad at solving these
> > problems though and I'm the problem.
> >
> > The consequence of this is that even though I put a lot of effort in my
> > code trying to avoid exceptions, I can never actually know that I have
> > succeeded unless I'm very defensive and wrap all foreign calls in some
> > exception handling code.  There are APIs for this, but if I mess up
> > then I'm in a bad spot.
> >
> > My proposal is that exceptions becomes a closed type and they reflect
> > what Java calls "errors", which are things your program logic should
> > generally not handle but can choose to if it wants to (I think we call
> > these failures in Ocaml).  The two specific exceptions I can think if
> > that should exist are: Assertion_failure and Out of Memory.  Another
> > one that I think might be nice but is open for debate is a
> > Not_implemented_failure, I use something like this often while building
> > a system.  I'm sure there are a few more that people can think of are
> > meaningful, but the point is these represent pretty bad situations that
> > the program logic shouldn't handle except in special situations.
>
> Without wishing to open old debating wounds too much, the argument of
> exceptions as errors tends to come down as to whether the thing signalled
> by an exception is truly exceptional. Not_found, for example, in some
> scenarios is as unexpected or impossible as Invalid_argument. Historically,
> they're (ab)used for performance reasons, but some of the overhead of that
> is being addressed in flambda. Note that for some arguable design mistakes
> - e.g. End_of_file, you can use exception matching to get around this, e.g.
>
> match input_line ch with
> | data -> ...
> | exception End_of_file -> ...
>
> which means that the old pattern
>
> let data = try Some (input_line ch) with End_of_file -> None
>
> is only needed if you need to compile with OCaml < 4.02
>
> If you haven't come across it, https://caml.inria.fr/pub/old_
> caml_site/ocamlexc/ocamlexc.htm is an interesting piece of older research
> around dealing with handling exceptions.
>
> What your proposal does overlook slightly is the use of exceptions for
> actual flow control. See for example, an oldish post of Alain Frisch's at
> https://www.lexifi.com/blog/static-exceptions. However, uses of
> exceptions like this may at some point be subsumed by Algebraic Effects
> which are being worked on by various people, mostly with multicore OCaml in
> mind. There's lots of links to that in https://github.com/ocamllabs/
> ocaml-multicore/wiki as well as other literature elsewhere online.
>
> HTH,
>
>
> David
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs

[-- Attachment #2: Type: text/html, Size: 6126 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-20 11:21   ` Ivan Gotovchits
@ 2017-10-20 11:38     ` Simon Cruanes
  2017-10-20 16:54       ` Malcolm Matalka
  2017-10-24 13:30       ` Richard W.M. Jones
  0 siblings, 2 replies; 44+ messages in thread
From: Simon Cruanes @ 2017-10-20 11:38 UTC (permalink / raw)
  To: Ivan Gotovchits; +Cc: David Allsopp, caml-list, Malcolm Matalka

[-- Attachment #1: Type: text/plain, Size: 482 bytes --]

Exceptions are also very useful as control structures sometimes. For
example:

- exiting from a traversal (graph, tree, `Foo.iter` functions) early
- being able to return a result from any point in a very large algorithm
  (e.g. returning "sat" or "unsat" in a SAT solver, where the main
  algorithm can span several hundreds or thousands of lines).

-- 
Simon Cruanes

http://weusepgp.info/
key 49AA62B6, fingerprint 949F EB87 8F06 59C6 D7D3  7D8D 4AC0 1D08 49AA 62B6

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-20 11:38     ` Simon Cruanes
@ 2017-10-20 16:54       ` Malcolm Matalka
  2017-10-20 19:47         ` Simon Cruanes
  2017-10-24 13:30       ` Richard W.M. Jones
  1 sibling, 1 reply; 44+ messages in thread
From: Malcolm Matalka @ 2017-10-20 16:54 UTC (permalink / raw)
  To: Simon Cruanes; +Cc: Ivan Gotovchits, David Allsopp, caml-list

Simon Cruanes <simon.cruanes.2007@m4x.org> writes:

> Exceptions are also very useful as control structures sometimes. For
> example:
>
> - exiting from a traversal (graph, tree, `Foo.iter` functions) early
> - being able to return a result from any point in a very large algorithm
>   (e.g. returning "sat" or "unsat" in a SAT solver, where the main
>   algorithm can span several hundreds or thousands of lines).

Seems like monads address this as well.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-20 10:55 ` David Allsopp
  2017-10-20 11:21   ` Ivan Gotovchits
@ 2017-10-20 17:07   ` Malcolm Matalka
  1 sibling, 0 replies; 44+ messages in thread
From: Malcolm Matalka @ 2017-10-20 17:07 UTC (permalink / raw)
  To: David Allsopp; +Cc: caml-list

David Allsopp <dra-news@metastack.com> writes:

> Malcolm Matalka wrote:
>> I have a question in two parts:
>> 
>> 1. Would this be a good idea? Why? (I'll describe why I think it is)
>> 
>> 2. If it were a good idea, is it feasible to do?
>> 
>> Full question:
>> 
>> Despite exceptions being a part of the language, there is a trend in
>> many libraries to try to avoid using them.  While I cannot find it, I
>> recall someone (Daniel maybe?) saying that the standard API advice is
>> that exceptions should not cross API boundaries.
>> 
>> The short reason for why people seem to want to avoid exceptions (which
>> I agree with) is that they side step the type system for helping you
>> understand if your code is correct and handles all situations the code
>> might experience.  Since the exn type is open, it means that one can
>> add any exception they want so it's not even known what exceptions you
>> might get ahead of time.
>> 
>> Another aspect of exceptions, which might be more of my personal
>> experience, is that exceptions tend to be pretty useless after the
>> fact.  For example, forgetting to handle a Not_found exception is an
>> exercise in pain.  Maybe I'm just bad at this, but many exceptions just
>> aren't that useful.  End_of_file is another one that, IMO, makes the
>> program flow pretty awkward and if you have multiple files you're
>> reading from at the same time quite ugly.  I tend to use wrappers that
>> give me an option based API.  Maybe I just bad at solving these
>> problems though and I'm the problem.
>> 
>> The consequence of this is that even though I put a lot of effort in my
>> code trying to avoid exceptions, I can never actually know that I have
>> succeeded unless I'm very defensive and wrap all foreign calls in some
>> exception handling code.  There are APIs for this, but if I mess up
>> then I'm in a bad spot.
>> 
>> My proposal is that exceptions becomes a closed type and they reflect
>> what Java calls "errors", which are things your program logic should
>> generally not handle but can choose to if it wants to (I think we call
>> these failures in Ocaml).  The two specific exceptions I can think if
>> that should exist are: Assertion_failure and Out of Memory.  Another
>> one that I think might be nice but is open for debate is a
>> Not_implemented_failure, I use something like this often while building
>> a system.  I'm sure there are a few more that people can think of are
>> meaningful, but the point is these represent pretty bad situations that
>> the program logic shouldn't handle except in special situations.
>
> Without wishing to open old debating wounds too much, the argument of exceptions as errors tends to come down as to whether the thing
> signalled by an exception is truly exceptional. Not_found, for example, in some scenarios is as unexpected or impossible as
> Invalid_argument. Historically, they're (ab)used for performance reasons, but some of the overhead of that is being addressed in
> flambda. Note that for some arguable design mistakes - e.g. End_of_file, you can use exception matching to get around this, e.g.
>
> match input_line ch with
> | data -> ...
> | exception End_of_file -> ...
>
> which means that the old pattern
>
> let data = try Some (input_line ch) with End_of_file -> None
>
> is only needed if you need to compile with OCaml < 4.02
>
> If you haven't come across it, https://caml.inria.fr/pub/old_caml_site/ocamlexc/ocamlexc.htm is an interesting piece of older research around dealing with handling exceptions.
>
> What your proposal does overlook slightly is the use of exceptions for actual flow control. See for example, an oldish post of Alain
> Frisch's at https://www.lexifi.com/blog/static-exceptions. However, uses of exceptions like this may at some point be subsumed by Algebraic
> Effects which are being worked on by various people, mostly with multicore OCaml in mind. There's lots of links to that in
> https://github.com/ocamllabs/ocaml-multicore/wiki as well as other literature elsewhere online.
>
> HTH,
>
>
> David 

Thank you for the response and reading material.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-20 16:54       ` Malcolm Matalka
@ 2017-10-20 19:47         ` Simon Cruanes
  2017-10-21 21:15           ` Malcolm Matalka
  0 siblings, 1 reply; 44+ messages in thread
From: Simon Cruanes @ 2017-10-20 19:47 UTC (permalink / raw)
  To: Malcolm Matalka; +Cc: Ivan Gotovchits, David Allsopp, caml-list

[-- Attachment #1: Type: text/plain, Size: 334 bytes --]

> Seems like monads address this as well.

Perhaps, but at some significant cost in both convenience (>>=
everywhere) and performance (for pure algorithmics, probably not much
for systems programming).


-- 
Simon Cruanes

http://weusepgp.info/
key 49AA62B6, fingerprint 949F EB87 8F06 59C6 D7D3  7D8D 4AC0 1D08 49AA 62B6

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-20 19:47         ` Simon Cruanes
@ 2017-10-21 21:15           ` Malcolm Matalka
  0 siblings, 0 replies; 44+ messages in thread
From: Malcolm Matalka @ 2017-10-21 21:15 UTC (permalink / raw)
  To: Simon Cruanes; +Cc: Ivan Gotovchits, David Allsopp, caml-list

Simon Cruanes <simon.cruanes.2007@m4x.org> writes:

>> Seems like monads address this as well.
>
> Perhaps, but at some significant cost in both convenience (>>=
> everywhere) and performance (for pure algorithmics, probably not much
> for systems programming).

Maybe flambda will address the performance side of things.  I'd rather
have do-notation than exceptions if the (>>=) is annoying.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-20  9:56 [Caml-list] What if exn was not an open type? Malcolm Matalka
  2017-10-20 10:55 ` David Allsopp
@ 2017-10-21 21:28 ` Nathan Moreau
  2017-10-22 12:39   ` Malcolm Matalka
  1 sibling, 1 reply; 44+ messages in thread
From: Nathan Moreau @ 2017-10-21 21:28 UTC (permalink / raw)
  To: Malcolm Matalka; +Cc: caml users

Exceptions being an open type allows you to classify failures.

from Unix.ml:

let rec waitpid_non_intr pid =
try waitpid [] pid
with Unix_error (EINTR, _, _) -> waitpid_non_intr pid

With a closed type, there is not much you can do to ensure that you
catch the right type of exception here (matching on strings? seems
much worse).

Note that, as there is no break keyword in the language, you tend to
use exceptions for control flow to avoid rewriting your for loops to
while loops.

You can write some APIs without exposing exceptions, the same way that
you can write an API without exposing a global hash-table.

Exceptions are just a tool, that allow you to work around some
limitations / performance issues / make your life easier. Removing
them is impossible at this point for compatibility reasons, so all you
can do is avoid using them if it makes you sad (the same way you avoid
using some parts of the language when you program in c++ / ecmascript
/ whatever language du jour).

Nathan


On 20 October 2017 at 11:56, Malcolm Matalka <mmatalka@gmail.com> wrote:
> I have a question in two parts:
>
> 1. Would this be a good idea? Why? (I'll describe why I think it is)
>
> 2. If it were a good idea, is it feasible to do?
>
> Full question:
>
> Despite exceptions being a part of the language, there is a trend in
> many libraries to try to avoid using them.  While I cannot find it, I
> recall someone (Daniel maybe?) saying that the standard API advice is
> that exceptions should not cross API boundaries.
>
> The short reason for why people seem to want to avoid exceptions (which
> I agree with) is that they side step the type system for helping you
> understand if your code is correct and handles all situations the code
> might experience.  Since the exn type is open, it means that one can add
> any exception they want so it's not even known what exceptions you might
> get ahead of time.
>
> Another aspect of exceptions, which might be more of my personal
> experience, is that exceptions tend to be pretty useless after the
> fact.  For example, forgetting to handle a Not_found exception is an
> exercise in pain.  Maybe I'm just bad at this, but many exceptions just
> aren't that useful.  End_of_file is another one that, IMO, makes the
> program flow pretty awkward and if you have multiple files you're
> reading from at the same time quite ugly.  I tend to use wrappers that
> give me an option based API.  Maybe I just bad at solving these problems
> though and I'm the problem.
>
> The consequence of this is that even though I put a lot of effort in my
> code trying to avoid exceptions, I can never actually know that I have
> succeeded unless I'm very defensive and wrap all foreign calls in some
> exception handling code.  There are APIs for this, but if I mess up then
> I'm in a bad spot.
>
> My proposal is that exceptions becomes a closed type and they reflect
> what Java calls "errors", which are things your program logic should
> generally not handle but can choose to if it wants to (I think we call
> these failures in Ocaml).  The two specific exceptions I can think if
> that should exist are: Assertion_failure and Out of Memory.  Another one
> that I think might be nice but is open for debate is a
> Not_implemented_failure, I use something like this often while building
> a system.  I'm sure there are a few more that people can think of are
> meaningful, but the point is these represent pretty bad situations that
> the program logic shouldn't handle except in special situations.
>
> Thanks for reading,
> /Malcolm
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-21 21:28 ` Nathan Moreau
@ 2017-10-22 12:39   ` Malcolm Matalka
  2017-10-22 13:08     ` Nathan Moreau
  2017-10-24 11:11     ` SP
  0 siblings, 2 replies; 44+ messages in thread
From: Malcolm Matalka @ 2017-10-22 12:39 UTC (permalink / raw)
  To: Nathan Moreau; +Cc: caml users

Nathan Moreau <nathan.moreau@m4x.org> writes:

> Exceptions being an open type allows you to classify failures.
>
> from Unix.ml:
>
> let rec waitpid_non_intr pid =
> try waitpid [] pid
> with Unix_error (EINTR, _, _) -> waitpid_non_intr pid
>
> With a closed type, there is not much you can do to ensure that you
> catch the right type of exception here (matching on strings? seems
> much worse).

I'm one of those people that uses result everywhere + result monad where
the error case is a polymorphic variant.  This lets me get the value of
an open type with power of an exhaustive pattern match check.  No
strings needed.

>
> Note that, as there is no break keyword in the language, you tend to
> use exceptions for control flow to avoid rewriting your for loops to
> while loops.

This is exactly what monads and applicatives give you: a way to short
circuit computation when it's no longer needed.

>
> You can write some APIs without exposing exceptions, the same way that
> you can write an API without exposing a global hash-table.

I'm not sure what you mean here, I have not had to expose exceptions in
any APIs I've written.  I don't think they are bad APIs.

>
> Exceptions are just a tool, that allow you to work around some
> limitations / performance issues / make your life easier. Removing
> them is impossible at this point for compatibility reasons, so all you
> can do is avoid using them if it makes you sad (the same way you avoid
> using some parts of the language when you program in c++ / ecmascript
> / whatever language du jour).

My point is that I cannot avoid exceptions without being very defensive
in my code.  A dependency can always start throwing an exception and I
have no tool to help me find that automatically.

>
> Nathan
>
>
> On 20 October 2017 at 11:56, Malcolm Matalka <mmatalka@gmail.com> wrote:
>> I have a question in two parts:
>>
>> 1. Would this be a good idea? Why? (I'll describe why I think it is)
>>
>> 2. If it were a good idea, is it feasible to do?
>>
>> Full question:
>>
>> Despite exceptions being a part of the language, there is a trend in
>> many libraries to try to avoid using them.  While I cannot find it, I
>> recall someone (Daniel maybe?) saying that the standard API advice is
>> that exceptions should not cross API boundaries.
>>
>> The short reason for why people seem to want to avoid exceptions (which
>> I agree with) is that they side step the type system for helping you
>> understand if your code is correct and handles all situations the code
>> might experience.  Since the exn type is open, it means that one can add
>> any exception they want so it's not even known what exceptions you might
>> get ahead of time.
>>
>> Another aspect of exceptions, which might be more of my personal
>> experience, is that exceptions tend to be pretty useless after the
>> fact.  For example, forgetting to handle a Not_found exception is an
>> exercise in pain.  Maybe I'm just bad at this, but many exceptions just
>> aren't that useful.  End_of_file is another one that, IMO, makes the
>> program flow pretty awkward and if you have multiple files you're
>> reading from at the same time quite ugly.  I tend to use wrappers that
>> give me an option based API.  Maybe I just bad at solving these problems
>> though and I'm the problem.
>>
>> The consequence of this is that even though I put a lot of effort in my
>> code trying to avoid exceptions, I can never actually know that I have
>> succeeded unless I'm very defensive and wrap all foreign calls in some
>> exception handling code.  There are APIs for this, but if I mess up then
>> I'm in a bad spot.
>>
>> My proposal is that exceptions becomes a closed type and they reflect
>> what Java calls "errors", which are things your program logic should
>> generally not handle but can choose to if it wants to (I think we call
>> these failures in Ocaml).  The two specific exceptions I can think if
>> that should exist are: Assertion_failure and Out of Memory.  Another one
>> that I think might be nice but is open for debate is a
>> Not_implemented_failure, I use something like this often while building
>> a system.  I'm sure there are a few more that people can think of are
>> meaningful, but the point is these represent pretty bad situations that
>> the program logic shouldn't handle except in special situations.
>>
>> Thanks for reading,
>> /Malcolm
>>
>> --
>> Caml-list mailing list.  Subscription management and archives:
>> https://sympa.inria.fr/sympa/arc/caml-list
>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>> Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-22 12:39   ` Malcolm Matalka
@ 2017-10-22 13:08     ` Nathan Moreau
  2017-10-24 11:11     ` SP
  1 sibling, 0 replies; 44+ messages in thread
From: Nathan Moreau @ 2017-10-22 13:08 UTC (permalink / raw)
  To: Malcolm Matalka; +Cc: caml users

> I'm one of those people that uses result everywhere + result monad where
> the error case is a polymorphic variant.  This lets me get the value of
> an open type with power of an exhaustive pattern match check.  No
> strings needed.


> My point is that I cannot avoid exceptions without being very defensive
> in my code.  A dependency can always start throwing an exception and I
> have no tool to help me find that automatically.

1. Polymorphic variants have not always been in the language.

2. Of course you are free to design your APIs the way you want;
however, when you accept a dependency, there is no work around reading
the documentation to know if exceptions can be thrown. The kind of
language that allow you to do that is not ocaml.

>> Note that, as there is no break keyword in the language, you tend to
>> use exceptions for control flow to avoid rewriting your for loops to
>> while loops.

> This is exactly what monads and applicatives give you: a way to short
> circuit computation when it's no longer needed.

Yes, just another tool, for other kind of situations. There are
scenarios where exceptions are more appropriate than sophisticated
type mechanisms.

On 22 October 2017 at 14:39, Malcolm Matalka <mmatalka@gmail.com> wrote:
> Nathan Moreau <nathan.moreau@m4x.org> writes:
>
>> Exceptions being an open type allows you to classify failures.
>>
>> from Unix.ml:
>>
>> let rec waitpid_non_intr pid =
>> try waitpid [] pid
>> with Unix_error (EINTR, _, _) -> waitpid_non_intr pid
>>
>> With a closed type, there is not much you can do to ensure that you
>> catch the right type of exception here (matching on strings? seems
>> much worse).
>
> I'm one of those people that uses result everywhere + result monad where
> the error case is a polymorphic variant.  This lets me get the value of
> an open type with power of an exhaustive pattern match check.  No
> strings needed.
>
>>
>> Note that, as there is no break keyword in the language, you tend to
>> use exceptions for control flow to avoid rewriting your for loops to
>> while loops.
>
> This is exactly what monads and applicatives give you: a way to short
> circuit computation when it's no longer needed.
>
>>
>> You can write some APIs without exposing exceptions, the same way that
>> you can write an API without exposing a global hash-table.
>
> I'm not sure what you mean here, I have not had to expose exceptions in
> any APIs I've written.  I don't think they are bad APIs.
>
>>
>> Exceptions are just a tool, that allow you to work around some
>> limitations / performance issues / make your life easier. Removing
>> them is impossible at this point for compatibility reasons, so all you
>> can do is avoid using them if it makes you sad (the same way you avoid
>> using some parts of the language when you program in c++ / ecmascript
>> / whatever language du jour).
>
> My point is that I cannot avoid exceptions without being very defensive
> in my code.  A dependency can always start throwing an exception and I
> have no tool to help me find that automatically.
>
>>
>> Nathan
>>
>>
>> On 20 October 2017 at 11:56, Malcolm Matalka <mmatalka@gmail.com> wrote:
>>> I have a question in two parts:
>>>
>>> 1. Would this be a good idea? Why? (I'll describe why I think it is)
>>>
>>> 2. If it were a good idea, is it feasible to do?
>>>
>>> Full question:
>>>
>>> Despite exceptions being a part of the language, there is a trend in
>>> many libraries to try to avoid using them.  While I cannot find it, I
>>> recall someone (Daniel maybe?) saying that the standard API advice is
>>> that exceptions should not cross API boundaries.
>>>
>>> The short reason for why people seem to want to avoid exceptions (which
>>> I agree with) is that they side step the type system for helping you
>>> understand if your code is correct and handles all situations the code
>>> might experience.  Since the exn type is open, it means that one can add
>>> any exception they want so it's not even known what exceptions you might
>>> get ahead of time.
>>>
>>> Another aspect of exceptions, which might be more of my personal
>>> experience, is that exceptions tend to be pretty useless after the
>>> fact.  For example, forgetting to handle a Not_found exception is an
>>> exercise in pain.  Maybe I'm just bad at this, but many exceptions just
>>> aren't that useful.  End_of_file is another one that, IMO, makes the
>>> program flow pretty awkward and if you have multiple files you're
>>> reading from at the same time quite ugly.  I tend to use wrappers that
>>> give me an option based API.  Maybe I just bad at solving these problems
>>> though and I'm the problem.
>>>
>>> The consequence of this is that even though I put a lot of effort in my
>>> code trying to avoid exceptions, I can never actually know that I have
>>> succeeded unless I'm very defensive and wrap all foreign calls in some
>>> exception handling code.  There are APIs for this, but if I mess up then
>>> I'm in a bad spot.
>>>
>>> My proposal is that exceptions becomes a closed type and they reflect
>>> what Java calls "errors", which are things your program logic should
>>> generally not handle but can choose to if it wants to (I think we call
>>> these failures in Ocaml).  The two specific exceptions I can think if
>>> that should exist are: Assertion_failure and Out of Memory.  Another one
>>> that I think might be nice but is open for debate is a
>>> Not_implemented_failure, I use something like this often while building
>>> a system.  I'm sure there are a few more that people can think of are
>>> meaningful, but the point is these represent pretty bad situations that
>>> the program logic shouldn't handle except in special situations.
>>>
>>> Thanks for reading,
>>> /Malcolm
>>>
>>> --
>>> Caml-list mailing list.  Subscription management and archives:
>>> https://sympa.inria.fr/sympa/arc/caml-list
>>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>>> Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-22 12:39   ` Malcolm Matalka
  2017-10-22 13:08     ` Nathan Moreau
@ 2017-10-24 11:11     ` SP
  2017-10-24 11:16       ` Gabriel Scherer
  1 sibling, 1 reply; 44+ messages in thread
From: SP @ 2017-10-24 11:11 UTC (permalink / raw)
  To: caml-list

On 22/10/2017 13:39, Malcolm Matalka wrote:
> I'm one of those people that uses result everywhere + result monad where
> the error case is a polymorphic variant.  This lets me get the value of
> an open type with power of an exhaustive pattern match check.  No
> strings needed.

Nice!

-- 
    SP

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-24 11:11     ` SP
@ 2017-10-24 11:16       ` Gabriel Scherer
  2017-10-25 11:30         ` Malcolm Matalka
  0 siblings, 1 reply; 44+ messages in thread
From: Gabriel Scherer @ 2017-10-24 11:16 UTC (permalink / raw)
  To: SP; +Cc: caml users

[-- Attachment #1: Type: text/plain, Size: 1544 bytes --]

Participants to this discussion may be interested in the article "Catch me
if you can", by David Teller, Arnaud Spiwack and Till Varoquaux, 2008:

  https://hal.inria.fr/inria-00432575

This is the year 2008 and ML-style exceptions are everywhere. Most modern
> languages, whether academic or industrial, feature some variant of this
> mechanism. Languages such as Java even feature static coverage-checking for
> such exceptions, something not available for ML languages, at least not
> without resorting to external tools. In this document, we demonstrate a
> design principle and a tiny library for managing errors in a functional
> manner, with static coverage-checking, automatically-inferred, structurally
> typed and hierarchical exceptional cases, with a reasonable run-time
> penalty. Our work is based on OCaml and features monads, polymorphic
> variants, compile-time code rewriting and trace elements of black magic.


On Tue, Oct 24, 2017 at 1:11 PM, SP <sp@orbitalfox.com> wrote:

> On 22/10/2017 13:39, Malcolm Matalka wrote:
> > I'm one of those people that uses result everywhere + result monad where
> > the error case is a polymorphic variant.  This lets me get the value of
> > an open type with power of an exhaustive pattern match check.  No
> > strings needed.
>
> Nice!
>
> --
>     SP
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>

[-- Attachment #2: Type: text/html, Size: 2506 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-20 11:38     ` Simon Cruanes
  2017-10-20 16:54       ` Malcolm Matalka
@ 2017-10-24 13:30       ` Richard W.M. Jones
  2017-10-24 19:02         ` Petter A. Urkedal
       [not found]         ` <CALa9pHQ-nhWf4T0U5gDiKTduPiEeXSZPQ=DY6N1YNbCXqRohPQ@mail.gmail.com>
  1 sibling, 2 replies; 44+ messages in thread
From: Richard W.M. Jones @ 2017-10-24 13:30 UTC (permalink / raw)
  To: Simon Cruanes; +Cc: Ivan Gotovchits, David Allsopp, caml-list, Malcolm Matalka

On Fri, Oct 20, 2017 at 01:38:16PM +0200, Simon Cruanes wrote:
> Exceptions are also very useful as control structures sometimes. For
> example:
> 
> - exiting from a traversal (graph, tree, `Foo.iter` functions) early
> - being able to return a result from any point in a very large algorithm
>   (e.g. returning "sat" or "unsat" in a SAT solver, where the main
>   algorithm can span several hundreds or thousands of lines).

Since I first used OCaml I have wished for a simple (and type safe)
return statement.

Rich.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-24 13:30       ` Richard W.M. Jones
@ 2017-10-24 19:02         ` Petter A. Urkedal
  2017-11-04 18:44           ` Richard W.M. Jones
       [not found]         ` <CALa9pHQ-nhWf4T0U5gDiKTduPiEeXSZPQ=DY6N1YNbCXqRohPQ@mail.gmail.com>
  1 sibling, 1 reply; 44+ messages in thread
From: Petter A. Urkedal @ 2017-10-24 19:02 UTC (permalink / raw)
  To: caml-list

On 24 October 2017 at 15:30, Richard W.M. Jones <rich@annexia.org> wrote:
> Since I first used OCaml I have wished for a simple (and type safe)
> return statement.

It's possible to wrap a bit type (and exception) safety about
exceptions used for return:

  val with_return : (('a -> 'b) -> 'a) -> 'a

  let with_return (type b) f =
    let exception Return of b in
    try f (fun y -> raise (Return y)) with Return y -> y

E.g.

  with_return (fun return -> List.iter (function 0 -> () | i -> return
i) [0; 0; 24; 0]; -1);;

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
       [not found]         ` <CALa9pHQ-nhWf4T0U5gDiKTduPiEeXSZPQ=DY6N1YNbCXqRohPQ@mail.gmail.com>
@ 2017-10-25  8:35           ` Richard W.M. Jones
  2017-10-25  9:12             ` Philippe Veber
                               ` (3 more replies)
  0 siblings, 4 replies; 44+ messages in thread
From: Richard W.M. Jones @ 2017-10-25  8:35 UTC (permalink / raw)
  To: Petter A. Urkedal; +Cc: ptoscano, caml-list

On Tue, Oct 24, 2017 at 09:00:05PM +0200, Petter A. Urkedal wrote:
> On 24 October 2017 at 15:30, Richard W.M. Jones <rich@annexia.org> wrote:
> > Since I first used OCaml I have wished for a simple (and type safe)
> > return statement.
> 
> It's possible to wrap a bit type (and exception) safety about
> exceptions used for return:
> 
>   val with_return : (('a -> 'b) -> 'a) -> 'a
> 
>   let with_return (type b) f =
>     let exception Return of b in
>     try f (fun y -> raise (Return y)) with Return y -> y
> 
> E.g.
> 
>   with_return (fun return -> List.iter (function 0 -> () | i -> return
> i) [0; 0; 24; 0]; -1);;

Thanks, that's interesting.

	--

As mine was a bit of a "Hit and run" comment, let me expand on
why a return statement is useful for the kind of dull code that
I write.

I often have to write functions of the form:

  let f () =
    if some_problem then (
      printf "sorry, can't do that\n";
      (* return *)
    )
    else if some_other_problem then (
      printf "sorry, can't do that either\n";
      (* return *)
    )
    else (
      match something with
      | None ->
         (* return *)
      | Some v ->
         (* finally we get to do some work! *)
         ...
    )

Real code is often heavily indented, or we have to put the work into
awkward nested functions.  This file contains a few real examples:
https://github.com/libguestfs/libguestfs/blob/master/daemon/inspect_fs_unix_fstab.ml

This would work a lot better with a return statement rather than
workarounds.

Having said all that I was writing a little ML language last
year and I tried to implement a return statement, but it was very
awkward to work out how to map that to my lambda calculus, so
I understand how return statements are rather difficult to implement
in practice.

Rich.

-- 
Richard Jones

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-25  8:35           ` Richard W.M. Jones
@ 2017-10-25  9:12             ` Philippe Veber
  2017-10-25 14:52               ` Richard W.M. Jones
  2017-10-25 13:36             ` Ivan Gotovchits
                               ` (2 subsequent siblings)
  3 siblings, 1 reply; 44+ messages in thread
From: Philippe Veber @ 2017-10-25  9:12 UTC (permalink / raw)
  To: Richard W.M. Jones; +Cc: Petter A. Urkedal, ptoscano, caml users

[-- Attachment #1: Type: text/plain, Size: 1618 bytes --]

2017-10-25 10:35 GMT+02:00 Richard W.M. Jones <rich@annexia.org>:

> On Tue, Oct 24, 2017 at 09:00:05PM +0200, Petter A. Urkedal wrote:
> > On 24 October 2017 at 15:30, Richard W.M. Jones <rich@annexia.org>
> wrote:
> > > Since I first used OCaml I have wished for a simple (and type safe)
> > > return statement.
> >
> > It's possible to wrap a bit type (and exception) safety about
> > exceptions used for return:
> >
> >   val with_return : (('a -> 'b) -> 'a) -> 'a
> >
> >   let with_return (type b) f =
> >     let exception Return of b in
> >     try f (fun y -> raise (Return y)) with Return y -> y
> >
> > E.g.
> >
> >   with_return (fun return -> List.iter (function 0 -> () | i -> return
> > i) [0; 0; 24; 0]; -1);;
>
> Thanks, that's interesting.
>
>         --
>
> As mine was a bit of a "Hit and run" comment, let me expand on
> why a return statement is useful for the kind of dull code that
> I write.
>
> I often have to write functions of the form:
>
>   let f () =
>     if some_problem then (
>       printf "sorry, can't do that\n";
>       (* return *)
>     )
>     else if some_other_problem then (
>       printf "sorry, can't do that either\n";
>       (* return *)
>     )
>     else (
>       match something with
>       | None ->
>          (* return *)
>       | Some v ->
>          (* finally we get to do some work! *)
>          ...
>     )
>
>
Hi Richard,

isn't that a context where error monads do a pretty decent job?

check_some_problem () >>= fun () ->
check_some_other_problem () >>= fun () ->
expect_something () >>= fun something ->
finally_do something

Cheers,
  Philippe.

[-- Attachment #2: Type: text/html, Size: 2561 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-24 11:16       ` Gabriel Scherer
@ 2017-10-25 11:30         ` Malcolm Matalka
  0 siblings, 0 replies; 44+ messages in thread
From: Malcolm Matalka @ 2017-10-25 11:30 UTC (permalink / raw)
  To: Gabriel Scherer; +Cc: SP, caml users

Gabriel Scherer <gabriel.scherer@gmail.com> writes:

> Participants to this discussion may be interested in the article "Catch me
> if you can", by David Teller, Arnaud Spiwack and Till Varoquaux, 2008:
>
>   https://hal.inria.fr/inria-00432575

Thank you for this, Gabriel, very interesting.

>
> This is the year 2008 and ML-style exceptions are everywhere. Most modern
>> languages, whether academic or industrial, feature some variant of this
>> mechanism. Languages such as Java even feature static coverage-checking for
>> such exceptions, something not available for ML languages, at least not
>> without resorting to external tools. In this document, we demonstrate a
>> design principle and a tiny library for managing errors in a functional
>> manner, with static coverage-checking, automatically-inferred, structurally
>> typed and hierarchical exceptional cases, with a reasonable run-time
>> penalty. Our work is based on OCaml and features monads, polymorphic
>> variants, compile-time code rewriting and trace elements of black magic.
>
>
> On Tue, Oct 24, 2017 at 1:11 PM, SP <sp@orbitalfox.com> wrote:
>
>> On 22/10/2017 13:39, Malcolm Matalka wrote:
>> > I'm one of those people that uses result everywhere + result monad where
>> > the error case is a polymorphic variant.  This lets me get the value of
>> > an open type with power of an exhaustive pattern match check.  No
>> > strings needed.
>>
>> Nice!
>>
>> --
>>     SP
>>
>> --
>> Caml-list mailing list.  Subscription management and archives:
>> https://sympa.inria.fr/sympa/arc/caml-list
>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-25  8:35           ` Richard W.M. Jones
  2017-10-25  9:12             ` Philippe Veber
@ 2017-10-25 13:36             ` Ivan Gotovchits
  2017-10-26  7:31             ` Petter A. Urkedal
  2017-10-27 13:58             ` Oleg
  3 siblings, 0 replies; 44+ messages in thread
From: Ivan Gotovchits @ 2017-10-25 13:36 UTC (permalink / raw)
  To: Richard W.M. Jones; +Cc: Petter A. Urkedal, ptoscano, caml-list

[-- Attachment #1: Type: text/plain, Size: 5626 bytes --]

On Wed, Oct 25, 2017 at 4:35 AM, Richard W.M. Jones <rich@annexia.org>
wrote:

>
> Having said all that I was writing a little ML language last
> year and I tried to implement a return statement, but it was very
> awkward to work out how to map that to my lambda calculus, so
> I understand how return statements are rather difficult to implement
> in practice.
>
> Rich.
>
>

The return statement is in fact a tamed exception, as it provides an
exceptional, i.e., a non-local control flow. However, exceptions are not
first class citizens in functional programming languages as they are not
explicitly represented in typed lambda calculus, and are not really
represented in the type system (in a sence that an expression with and
without exception has the same type). Thus dealing with expressions that
may raise an exception is hard, as well as dealing with any expression that
has a side effect. OCaml multicore project is actually bringing more than
the multicore support, they also reify the effect system into the language.
Thus exceptions, as well as the return statements, can be soon easily
implemented on top of the effect system and can be reasoned in a much more
natural way.

With all that said, safe and first class exceptions can be implemented in
plain OCaml, or any other functional programming language that provides
higher order polymorphism (type classes, functors, etc). The limited form
of an exception can be implemented even without it. As it was already
noticed, the Maybe monad, as well as the Error monad, or any other monad
that reifies non-total computations can be used to implement a poor man
return statement. The problem is that when one computation yields the null
value, the rest of the computation chain is still evaluated. This is not a
big issue if a chain is written manually (i.e., is a block of code, like in
your example), but it could be serious if the chain is very long (i.e.,
processing a big list), or even worse infininte. If the problem with a list
of computations can be solved on the monad implementation (as we do in the
[Monads][2] library), the problem with the infinite computation can be
easily addressed in a non-total monad.

The answer is to use the continuation passing style (CPS). We can use
delimited continuations (as in the upcoming multicore), or we can use plain
non-delimited continuations. The rough idea, is that if you have function
that needs to escape the computation prematurely, you can pass a
continuation to that function, e.g.,

     let do_stuff return =
       if world_is_bad then return None
       else if moon_phase_is_bad then return None
       else return (compute_some_stuff ())

You may notice, that we still need the else statement as our return
function has type `'a -> 'a`, but for the non-local return we need
something of type `'a -> 'b`, to implement this we need to switch to the
continuation passing style, where each computation is a continuation, i.e.,
a function of type `('a -> 'b) -> 'b`. For example, this is how the
List.fold function will look in the CPS:

        let fold xs ~init ~f =
          let rec loop xs k = match xs with
            | [] -> k
            | x :: xs -> fun k' ->  k (fun a -> loop xs (f a x) k') in
          loop xs (fun k -> k init)

Programming in this style directly is a little bit cubersome, but the good
news, is that the continuation passing style can be encoded as a monad. The
[Continuation monad][2] has only one extra operator, called call/cc, that
calls a function and passes the current continuation (i.e., a first class
return statement) to it, e.g.,

       let do_stuff ~cc:return =
         if world_is_bad then return () >>= fun () ->
         if moon_phase_is_bad then return () >>= fun () ->
         compute_some_stuff ()

     let main () = Cont.call do_stuff

The interesting thing with the non-delimited continuation is that  `cc`
here is a first class value that can be stored in a container, resumed
multiple times, etc. This gives us enough freedom to implement lots of
weird variants of a control flow, e.g., return statement, exceptions,
couroutines, concurrency, and, probably, even the [COMEFROM][4]
instruction. Basically, a continuation is a first class program label.

Is it good or bad, you can decide yourself. Maybe this is too much freedom,
however, this is totally a part of the lambda calculus, and is not using
any type system escape hatches, like exceptions, even given that the
`return` function has type `a -> 'b t`.

P.S. Although I took your examples for demonstration purposes of the Cont
monad, I still believe that for your particular case a non-total monad
would be much nicer and more natural. Using the Monads library Error monad,
it can be expressed as:

   let do_stuff () =
     if world_is_bad then failf "the world is wrong" () >>= fun () ->
     if moon_phase_is_bad then failf "look at the Moon!" () >>= fun () ->
     compute_some_stuff ()

The Error monad implements the Fail interface, that provides mechanisms for
diverging the computation with an exception (not real exception of course),
as well as provides the catch operator. The Error monad has a much stricter
type discipline, and limited control flow variants, that can be considered
as boon in most cases.


[1]: http://kcsrk.info/ocaml/multicore/2015/05/20/effects-multicore/
[2]: http://binaryanalysisplatform.github.io/bap/api/v1.3.0/Monads.Std.html
[3]:
http://binaryanalysisplatform.github.io/bap/api/v1.3.0/Monads.Std.Monad.Cont.html
[4]: https://en.wikipedia.org/wiki/COMEFROM
[5]:
http://binaryanalysisplatform.github.io/bap/api/v1.3.0/Monads.Std.Monad.Fail.S.html

[-- Attachment #2: Type: text/html, Size: 7240 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-25  9:12             ` Philippe Veber
@ 2017-10-25 14:52               ` Richard W.M. Jones
  2017-10-25 16:37                 ` Ivan Gotovchits
  2017-10-26  8:06                 ` Malcolm Matalka
  0 siblings, 2 replies; 44+ messages in thread
From: Richard W.M. Jones @ 2017-10-25 14:52 UTC (permalink / raw)
  To: Philippe Veber; +Cc: Petter A. Urkedal, ptoscano, caml users

On Wed, Oct 25, 2017 at 11:12:26AM +0200, Philippe Veber wrote:
> isn't that a context where error monads do a pretty decent job?
> 
> check_some_problem () >>= fun () ->
> check_some_other_problem () >>= fun () ->
> expect_something () >>= fun something ->
> finally_do something

Right, but the main problem with monads is they scare off ordinary
programmers :-/

When writing open source code in OCaml we have two -- conflicting --
goals.  Goal #1 is to write elegant, short, fast, safe code, and OCaml
really wins there.  Goal #2 is to attract outside programmers to work
on the project, and that's pretty hard with OCaml code, but we manage
it.  But it gets much much harder if we use any concept which strays
too far from imperative/C-like code.  You will see if you look through
our codebase that it's pretty imperative and -- quite deliberately --
avoids doing strange stuff with modules, functors or really anything
which is "excessively functional" (sorry for the loose term, but I
hope you know what I mean :-).

However when I have the time after my current conference I will try
to rewrite the code I linked to with monads to see if I can make
something which is both simple and readable.

Thanks,

Rich.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-25 14:52               ` Richard W.M. Jones
@ 2017-10-25 16:37                 ` Ivan Gotovchits
  2017-10-25 17:47                   ` SP
  2017-10-26  8:06                 ` Malcolm Matalka
  1 sibling, 1 reply; 44+ messages in thread
From: Ivan Gotovchits @ 2017-10-25 16:37 UTC (permalink / raw)
  To: Richard W.M. Jones
  Cc: Philippe Veber, Petter A. Urkedal, ptoscano, caml users

[-- Attachment #1: Type: text/plain, Size: 4053 bytes --]

Well, we have the same constraint, as we are trying to write code, that is
understandable by students, who may not know OCaml. However, we are also
trying to enforce pure functional programming, that, we believe, teaches
the right thinking and produces programs that are easier to understand.
When you need to write system code or any code that deals with effects,
monads become inevitable sooner or later unless you're willing to use
the escape hatch of mutability. The monadic code usually scares people (and
the Continuation monad usually scared even the bravest). However, there are
ways to deal with it. You can use different syntax extensions, like the
[ppx_let][1], that is very light, [ppx_monadic][2], that provides a real
do-notation so that you can write your code in the true imperative style.
You can even rely on camlp4 or camlp5 do provide you a full support for the
do-notation.

I, myself, do not really like the do-notation (even in Haskell, or F#)
because I believe, that it hides the real notion of computation. So, we
stick to the regular syntax of OCaml. I'm always explaining the concept of
Monad using the imperative C-like language, by pointing that a monad is
just a way to parametrize your semicolon operator. So the idea is not
really from functional programming and should be understandable by someone
who has only an imperative programming background.

With all this said, I think, that your code should rely on exceptions, not
the monads. Since libguestfs is totally imperative library, that deals with
imperative primitives, using OCaml exceptions is a perfectly valid
solution. You are already dealing with primitives that bear hidden effects,
so your computations are not pure on the first hand, thus adding exceptions
will not add anything more to it. The essence of each monad is the `run`
function, that evaluates monadic operations (orders) and produces an
explicit state. Since you can't really reify the run function in your case,
using monads will only obscure things. To make the long story short, you
should use monad only with pure code in cases when you can represent
effects as an OCaml value. Mixing imperative code with monadic code is the
worst thing one can imagine - as you will deal with wolves in lamb's skins,
functions that pretend to be pure while in fact, they are inherently
effectful.


[1]: https://blog.janestreet.com/let-syntax-and-why-you-should-use-it/
[2]: https://bitbucket.org/camlspotter/ppx_monadic

On Wed, Oct 25, 2017 at 10:52 AM, Richard W.M. Jones <rich@annexia.org>
wrote:

> On Wed, Oct 25, 2017 at 11:12:26AM +0200, Philippe Veber wrote:
> > isn't that a context where error monads do a pretty decent job?
> >
> > check_some_problem () >>= fun () ->
> > check_some_other_problem () >>= fun () ->
> > expect_something () >>= fun something ->
> > finally_do something
>
> Right, but the main problem with monads is they scare off ordinary
> programmers :-/
>
> When writing open source code in OCaml we have two -- conflicting --
> goals.  Goal #1 is to write elegant, short, fast, safe code, and OCaml
> really wins there.  Goal #2 is to attract outside programmers to work
> on the project, and that's pretty hard with OCaml code, but we manage
> it.  But it gets much much harder if we use any concept which strays
> too far from imperative/C-like code.  You will see if you look through
> our codebase that it's pretty imperative and -- quite deliberately --
> avoids doing strange stuff with modules, functors or really anything
> which is "excessively functional" (sorry for the loose term, but I
> hope you know what I mean :-).
>
> However when I have the time after my current conference I will try
> to rewrite the code I linked to with monads to see if I can make
> something which is both simple and readable.
>
> Thanks,
>
> Rich.
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>

[-- Attachment #2: Type: text/html, Size: 5147 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-25 16:37                 ` Ivan Gotovchits
@ 2017-10-25 17:47                   ` SP
  0 siblings, 0 replies; 44+ messages in thread
From: SP @ 2017-10-25 17:47 UTC (permalink / raw)
  To: caml-list

On 25/10/2017 17:37, Ivan Gotovchits wrote:
> With all this said, I think, that your code should rely on exceptions, not
> the monads. Since libguestfs is totally imperative library, that deals with
> imperative primitives, using OCaml exceptions is a perfectly valid
> solution. 
But try, if you can, to not let these exceptions cross any of your APIs.

-- 
    SP

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-25  8:35           ` Richard W.M. Jones
  2017-10-25  9:12             ` Philippe Veber
  2017-10-25 13:36             ` Ivan Gotovchits
@ 2017-10-26  7:31             ` Petter A. Urkedal
  2017-10-27 13:58             ` Oleg
  3 siblings, 0 replies; 44+ messages in thread
From: Petter A. Urkedal @ 2017-10-26  7:31 UTC (permalink / raw)
  To: Richard W.M. Jones; +Cc: ptoscano, caml users

On 25 October 2017 at 10:35, Richard W.M. Jones <rich@annexia.org> wrote:
> On Tue, Oct 24, 2017 at 09:00:05PM +0200, Petter A. Urkedal wrote:
>>   let with_return (type b) f =
>>     let exception Return of b in
>>     try f (fun y -> raise (Return y)) with Return y -> y

> As mine was a bit of a "Hit and run" comment, let me expand on
> why a return statement is useful for the kind of dull code that
> I write.
>
> I often have to write functions of the form:
>
>   let f () =
>     if some_problem then (
>       printf "sorry, can't do that\n";
>       (* return *)
>     )
>     else if some_other_problem then (
>       printf "sorry, can't do that either\n";
>       (* return *)
>     )
>     else (
>       match something with
>       | None ->
>          (* return *)
>       | Some v ->
>          (* finally we get to do some work! *)
>          ...
>     )

Using the above trick, this might be written in more C-like style as:

let f () =
  with_return @@ fun return ->

  if some_problem then (
    printf "sorry, can't do that\n";
    return ()
  );

  if some_other_problem then (
    printf "sorry, can't do that either\n";
    return ()
  );

  let v =
    match something with
    | None -> return ()
    | Some v -> v in

  (* finally we get to do some work! *)
  ...

However, I would have written it:

let f () =
  if some_problem then
    printf "sorry, can't do that\n" else

  if some_other_problem then
    printf "sorry, can't do that either\n" else

  (match something with
   | None ->
     (* return *)
   | Some v ->
     (* finally we get to do some work! *)
     ...)

That is, treating the if ... else more like let ... in.  However any ;
would chop of the bodies of the conditionals, so this style only works
when semicolons are parenthesised or rewritten as let () = ... in.
Especially, the latter must be used if one wants to skip indenting an
else block, but insert a debug statement:

let f () =
  if some_problem then
    printf "sorry, can't do that\n" else

  if some_other_problem then
    printf "sorry, can't do that either\n" else

  let () = printf "no problems\n" in

  (match something with
   | None ->
     (* return *)
   | Some v ->
     (* finally we get to do some work! *)
     ...)

> Real code is often heavily indented, or we have to put the work into
> awkward nested functions.  This file contains a few real examples:
> https://github.com/libguestfs/libguestfs/blob/master/daemon/inspect_fs_unix_fstab.ml
>
> This would work a lot better with a return statement rather than
> workarounds.

Given the change of formatting above, also changes the perception: The
issue now is not that the return is missing, but that one cannot *not*
return from a conditional.

Petter

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-25 14:52               ` Richard W.M. Jones
  2017-10-25 16:37                 ` Ivan Gotovchits
@ 2017-10-26  8:06                 ` Malcolm Matalka
  2017-10-26  8:11                   ` Xavier Leroy
  1 sibling, 1 reply; 44+ messages in thread
From: Malcolm Matalka @ 2017-10-26  8:06 UTC (permalink / raw)
  To: Richard W.M. Jones
  Cc: Philippe Veber, Petter A. Urkedal, ptoscano, caml users

"Richard W.M. Jones" <rich@annexia.org> writes:

> On Wed, Oct 25, 2017 at 11:12:26AM +0200, Philippe Veber wrote:
>> isn't that a context where error monads do a pretty decent job?
>> 
>> check_some_problem () >>= fun () ->
>> check_some_other_problem () >>= fun () ->
>> expect_something () >>= fun something ->
>> finally_do something
>
> Right, but the main problem with monads is they scare off ordinary
> programmers :-/

F# seems to have limited support for monads, but they call them
"workflows" and "computation statements" (or something like that).
Maybe just a name change would be sufficient for Ocaml folks.  We can
tell everyone it's just monads still, but we want to call them blah.  I
dunno, how effective that is.

>
> When writing open source code in OCaml we have two -- conflicting --
> goals.  Goal #1 is to write elegant, short, fast, safe code, and OCaml
> really wins there.  Goal #2 is to attract outside programmers to work
> on the project, and that's pretty hard with OCaml code, but we manage
> it.  But it gets much much harder if we use any concept which strays
> too far from imperative/C-like code.  You will see if you look through
> our codebase that it's pretty imperative and -- quite deliberately --
> avoids doing strange stuff with modules, functors or really anything
> which is "excessively functional" (sorry for the loose term, but I
> hope you know what I mean :-).
>
> However when I have the time after my current conference I will try
> to rewrite the code I linked to with monads to see if I can make
> something which is both simple and readable.
>
> Thanks,
>
> Rich.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-26  8:06                 ` Malcolm Matalka
@ 2017-10-26  8:11                   ` Xavier Leroy
  0 siblings, 0 replies; 44+ messages in thread
From: Xavier Leroy @ 2017-10-26  8:11 UTC (permalink / raw)
  To: caml-list

On 26/10/2017 10:06, Malcolm Matalka wrote:
> F# seems to have limited support for monads, but they call them
> "workflows" and "computation statements" (or something like that).
> Maybe just a name change would be sufficient for Ocaml folks.  We can
> tell everyone it's just monads still, but we want to call them blah.  I
> dunno, how effective that is.

Simon Peyton Jones suggested "warm fuzzy things" as a better name for monads.
There is even an Urban Dictionary entry about this:
https://www.urbandictionary.com/define.php?term=Warm%20Fuzzy%20Thing

- Xavier Leroy

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-25  8:35           ` Richard W.M. Jones
                               ` (2 preceding siblings ...)
  2017-10-26  7:31             ` Petter A. Urkedal
@ 2017-10-27 13:58             ` Oleg
  2017-10-27 14:24               ` Philippe Veber
  3 siblings, 1 reply; 44+ messages in thread
From: Oleg @ 2017-10-27 13:58 UTC (permalink / raw)
  To: rich; +Cc: ptoscano, caml-list


It is interesting that we have this discussion about, even advocacy
for, monads at the time effects are coming to the front stage. The
language Eff (http://eff-lang.org), which is essentially OCaml, states
right upfront its advantages over monads. (Monads do not compose.)
Daan Leijen talk past month about the web server implemented in Koka
stressed the absence of monads. In Koka, if we need an effectful
operation, we just do it. As the Multicore OCaml project has shown,
effects can be very efficiently implemented. 

I fully agree with Ivan Gotovchits that recommends Rich Jones' code
rely on exceptions rather than monads. Where I disagree is the
contention that ``When you need to write system code or any code that
deals with effects, monads become inevitable sooner or later unless
you're willing to use the escape hatch of mutability.'' Monads are not
inevitable!

First of all, not all effects can be represented as monads (which was
pointed long time ago by Wadler himself). My talk at the ML workshop
last month
        http://okmij.org/ftp/tagless-final/nondet-effect.html
described several other effects that aren't monadic and that
commitment to monads precludes several useful implementations (e.g.,
code generation, which cannot be thought in monadic terms).  Hence,
there is real harm in trying to squeeze everything into a
monad. Incidentally, alternative ideas of effects as interactions go
back to 1970s.

Richard W.M. Jones wrote:
> Having said all that I was writing a little ML language last
> year and I tried to implement a return statement, but it was very
> awkward to work out how to map that to my lambda calculus, so
> I understand how return statements are rather difficult to implement
> in practice.

Perhaps this gives a hint that lambda-calculus isn't the best model of
computation -- as the Founding Father has recognized very early
on. There is a reason he spent his life after ML working on process
calculi. Indeed, it takes lots of hops to implement a simple return
statement -- not to speak about real IO -- whereas it a process
calculus, we just say !a. Done. Sending the result to another process
(or to the context) is a built-in operation. There are no
continuations to pass around or capture, no monads (which become
totally unnecessary), no binding. Erlang has shown very well that this
way of programming is realistic, and rather effective.

lambda-calculus has its uses: it works spectacularly well for what it
has been designed for: expressing definitions (and logical
derivations). However, just because it is possible to express
arithmetic in lambda-calculus does not mean that we should be stuck
with Church-numerals. There are better ways to handle numbers -- and
there are better ways to handle communication and control -- outside
lambda-calculus.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-27 13:58             ` Oleg
@ 2017-10-27 14:24               ` Philippe Veber
  2017-10-27 14:49                 ` Leo White
  2017-11-01  7:16                 ` Oleg
  0 siblings, 2 replies; 44+ messages in thread
From: Philippe Veber @ 2017-10-27 14:24 UTC (permalink / raw)
  To: Oleg, Richard W.M. Jones, ptoscano, caml users

[-- Attachment #1: Type: text/plain, Size: 3882 bytes --]

Thanks Oleg, this is very interesting! I thought one big selling argument
of monads was also that the type of the functions shows which effect it
performs. As I understand it, it is not the case for effects, at least not
in existing implementations like multicore ocaml. Isn't this considered a
concern, just like exception-raising functions are increasingly discouraged
at the benefit of explicitly specifying partial functions with a result
type? Also, would you know a reference that shows that effects compose
indeed a lot more easily than monads? In my (very limited) experience,
composing two monads sometimes require a little thinking and not so trivial
implementation to be defined.

2017-10-27 15:58 GMT+02:00 Oleg <oleg@okmij.org>:

>
> It is interesting that we have this discussion about, even advocacy
> for, monads at the time effects are coming to the front stage. The
> language Eff (http://eff-lang.org), which is essentially OCaml, states
> right upfront its advantages over monads. (Monads do not compose.)
> Daan Leijen talk past month about the web server implemented in Koka
> stressed the absence of monads. In Koka, if we need an effectful
> operation, we just do it. As the Multicore OCaml project has shown,
> effects can be very efficiently implemented.
>
> I fully agree with Ivan Gotovchits that recommends Rich Jones' code
> rely on exceptions rather than monads. Where I disagree is the
> contention that ``When you need to write system code or any code that
> deals with effects, monads become inevitable sooner or later unless
> you're willing to use the escape hatch of mutability.'' Monads are not
> inevitable!
>
> First of all, not all effects can be represented as monads (which was
> pointed long time ago by Wadler himself). My talk at the ML workshop
> last month
>         http://okmij.org/ftp/tagless-final/nondet-effect.html
> described several other effects that aren't monadic and that
> commitment to monads precludes several useful implementations (e.g.,
> code generation, which cannot be thought in monadic terms).  Hence,
> there is real harm in trying to squeeze everything into a
> monad. Incidentally, alternative ideas of effects as interactions go
> back to 1970s.
>
> Richard W.M. Jones wrote:
> > Having said all that I was writing a little ML language last
> > year and I tried to implement a return statement, but it was very
> > awkward to work out how to map that to my lambda calculus, so
> > I understand how return statements are rather difficult to implement
> > in practice.
>
> Perhaps this gives a hint that lambda-calculus isn't the best model of
> computation -- as the Founding Father has recognized very early
> on. There is a reason he spent his life after ML working on process
> calculi. Indeed, it takes lots of hops to implement a simple return
> statement -- not to speak about real IO -- whereas it a process
> calculus, we just say !a. Done. Sending the result to another process
> (or to the context) is a built-in operation. There are no
> continuations to pass around or capture, no monads (which become
> totally unnecessary), no binding. Erlang has shown very well that this
> way of programming is realistic, and rather effective.
>
> lambda-calculus has its uses: it works spectacularly well for what it
> has been designed for: expressing definitions (and logical
> derivations). However, just because it is possible to express
> arithmetic in lambda-calculus does not mean that we should be stuck
> with Church-numerals. There are better ways to handle numbers -- and
> there are better ways to handle communication and control -- outside
> lambda-calculus.
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>

[-- Attachment #2: Type: text/html, Size: 4955 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-27 14:24               ` Philippe Veber
@ 2017-10-27 14:49                 ` Leo White
  2017-11-01  7:16                 ` Oleg
  1 sibling, 0 replies; 44+ messages in thread
From: Leo White @ 2017-10-27 14:49 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 617 bytes --]

> I thought one big selling argument of monads was also that the type of
> the functions shows which effect it performs. As I understand it, it
> is not the case for effects, at least not in existing implementations
> like multicore ocaml.
Whilst the current implementation in multicore OCaml does not track
effects at the type level,there is a prototype version which does:

    https://github.com/lpw25/ocaml-typed-effects

I spoke about it at HOPE last year:

    https://www.youtube.com/watch?v=ibpUJmlEWi4&list=PLnqUlCo055hVLWbmrXyxqYXcJJWSgU6Z5&index=1    http://www.lpw25.net/talks/hope2016.pdf

Regards,

Leo

[-- Attachment #2: Type: text/html, Size: 971 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-27 14:24               ` Philippe Veber
  2017-10-27 14:49                 ` Leo White
@ 2017-11-01  7:16                 ` Oleg
  2017-11-04 17:52                   ` Philippe Veber
  1 sibling, 1 reply; 44+ messages in thread
From: Oleg @ 2017-11-01  7:16 UTC (permalink / raw)
  To: philippe.veber; +Cc: caml-list, rich, nick.palladinos



> I thought one big selling argument of monads was also that the type of
> the functions shows which effect it performs. As I understand it, it
> is not the case for effects, at least not in existing implementations
> like multicore ocaml. ... Also, would you know a reference that shows
> that effects compose indeed a lot more easily than monads?

How expressive are the types of effectful computations pretty much
depends on a particular type system in use. Let me cite from the message
that I received from Nick Palladinos (CCed) the other week, who implemented
extensible effects in F#, a rather close relative of OCaml. You can
write the code as below

let example () =
    eff {
        do! put 1
        let! x = get ()
        let! y = ask ()
        return x + y
    }

(Here, `eff' is a tag of so-called computational expressions of F#, a
very handy feature).

The *inferred* type is as follows
  val example : unit -> Eff<'U,int> when 'U :> Reader<int> and 'U :> State<int>

clearly stating that example is an effectful expression that uses at
least Reader and State effects. The example also illustrates
composability, your second question: put/get and ask are operations of two
distinct effects (State and Reader, resp). You can combine them freely
within the same program.

(I hope Nick will write a paper explaining his implementation so that
we can all learn from it.)

To give more references (in addition to Leo's work), I should point to Koka
        https://koka-lang.github.io/koka/doc/kokaspec.html

which is an OCaml-like language based on effects and
effect-typing. The language is mature enough to write a web server in
it (as Daan Leijen described in his talk at the ML Family workshop
this year).

        Other references are the recent Effekt library in Scala
        http://b-studios.de/scala-effekt/
        and extensible-effect library
        http://okmij.org/ftp/Haskell/extensible/
which, although being first proposed for Haskell has also been ported
to Scala (and now F#). Purescript's extensible effects are also
similar.



^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-11-01  7:16                 ` Oleg
@ 2017-11-04 17:52                   ` Philippe Veber
  0 siblings, 0 replies; 44+ messages in thread
From: Philippe Veber @ 2017-11-04 17:52 UTC (permalink / raw)
  To: Oleg, Philippe Veber, caml users, Richard W.M. Jones, nick.palladinos

[-- Attachment #1: Type: text/plain, Size: 2279 bytes --]

Thanks a lot Leo and Oleg for all this very exciting material!

2017-11-01 8:16 GMT+01:00 Oleg <oleg@okmij.org>:

>
>
> > I thought one big selling argument of monads was also that the type of
> > the functions shows which effect it performs. As I understand it, it
> > is not the case for effects, at least not in existing implementations
> > like multicore ocaml. ... Also, would you know a reference that shows
> > that effects compose indeed a lot more easily than monads?
>
> How expressive are the types of effectful computations pretty much
> depends on a particular type system in use. Let me cite from the message
> that I received from Nick Palladinos (CCed) the other week, who implemented
> extensible effects in F#, a rather close relative of OCaml. You can
> write the code as below
>
> let example () =
>     eff {
>         do! put 1
>         let! x = get ()
>         let! y = ask ()
>         return x + y
>     }
>
> (Here, `eff' is a tag of so-called computational expressions of F#, a
> very handy feature).
>
> The *inferred* type is as follows
>   val example : unit -> Eff<'U,int> when 'U :> Reader<int> and 'U :>
> State<int>
>
> clearly stating that example is an effectful expression that uses at
> least Reader and State effects. The example also illustrates
> composability, your second question: put/get and ask are operations of two
> distinct effects (State and Reader, resp). You can combine them freely
> within the same program.
>
> (I hope Nick will write a paper explaining his implementation so that
> we can all learn from it.)
>
> To give more references (in addition to Leo's work), I should point to Koka
>         https://koka-lang.github.io/koka/doc/kokaspec.html
>
> which is an OCaml-like language based on effects and
> effect-typing. The language is mature enough to write a web server in
> it (as Daan Leijen described in his talk at the ML Family workshop
> this year).
>
>         Other references are the recent Effekt library in Scala
>         http://b-studios.de/scala-effekt/
>         and extensible-effect library
>         http://okmij.org/ftp/Haskell/extensible/
> which, although being first proposed for Haskell has also been ported
> to Scala (and now F#). Purescript's extensible effects are also
> similar.
>
>
>

[-- Attachment #2: Type: text/html, Size: 3176 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-10-24 19:02         ` Petter A. Urkedal
@ 2017-11-04 18:44           ` Richard W.M. Jones
  2017-11-04 18:48             ` SP
                               ` (3 more replies)
  0 siblings, 4 replies; 44+ messages in thread
From: Richard W.M. Jones @ 2017-11-04 18:44 UTC (permalink / raw)
  To: Petter A. Urkedal; +Cc: caml-list

On Tue, Oct 24, 2017 at 09:02:55PM +0200, Petter A. Urkedal wrote:
> On 24 October 2017 at 15:30, Richard W.M. Jones <rich@annexia.org> wrote:
> > Since I first used OCaml I have wished for a simple (and type safe)
> > return statement.
> 
> It's possible to wrap a bit type (and exception) safety about
> exceptions used for return:
> 
>   val with_return : (('a -> 'b) -> 'a) -> 'a
> 
>   let with_return (type b) f =
>     let exception Return of b in
>     try f (fun y -> raise (Return y)) with Return y -> y
> 
> E.g.
> 
>   with_return (fun return -> List.iter (function 0 -> () | i -> return
> i) [0; 0; 24; 0]; -1);;

As promised, I tried rewriting some code with this style.  The
good news is that it does look a lot more like the original C code.

The bad news is that with_return as defined above doesn't really work
like the C return statement, as in the small example below.  The
example is very contrived but it reflects a problem that I found in
real code.

The problem is that the return statement could be called from many
contexts, all with different types.  The compiler expects to unify all
these types (as the same type 'b) which is not possible.

It wasn't immediately clear to me if this was solvable.

Rich.

----------------------------------------------------------------------

let with_return (type b) f =
  let exception Return of b in
  try f (fun y -> raise (Return y)) with Return y -> y

let f () =
  with_return (fun return ->
      if false then return "error";
      let a =
        match Some "abc" with
        | None -> return "another error"
        | Some a -> a in
      a
  )



-- 
Richard Jones

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-11-04 18:44           ` Richard W.M. Jones
@ 2017-11-04 18:48             ` SP
  2017-11-04 18:53               ` Richard W.M. Jones
  2017-11-04 19:01             ` Max Mouratov
                               ` (2 subsequent siblings)
  3 siblings, 1 reply; 44+ messages in thread
From: SP @ 2017-11-04 18:48 UTC (permalink / raw)
  To: caml-list

On 04/11/2017 18:44, Richard W.M. Jones wrote:
> As promised, I tried rewriting some code with this style.  The
> good news is that it does look a lot more like the original C code.
> The bad news is that with_return as defined above doesn't really work
> like the C return statement, as in the small example below.  The
> example is very contrived but it reflects a problem that I found in
> real code.

The good news, is that if you really want to write this in C style, just
write it in C and bind to it from OCaml.

> The problem is that the return statement could be called from many
> contexts, all with different types.  The compiler expects to unify all
> these types (as the same type 'b) which is not possible.
> 
> It wasn't immediately clear to me if this was solvable.

I think you can define a generic return.


-- 
    SP

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-11-04 18:48             ` SP
@ 2017-11-04 18:53               ` Richard W.M. Jones
  2017-11-04 19:03                 ` SP
  0 siblings, 1 reply; 44+ messages in thread
From: Richard W.M. Jones @ 2017-11-04 18:53 UTC (permalink / raw)
  To: SP; +Cc: caml-list

On Sat, Nov 04, 2017 at 06:48:34PM +0000, SP wrote:
> On 04/11/2017 18:44, Richard W.M. Jones wrote:
> > As promised, I tried rewriting some code with this style.  The
> > good news is that it does look a lot more like the original C code.
> > The bad news is that with_return as defined above doesn't really work
> > like the C return statement, as in the small example below.  The
> > example is very contrived but it reflects a problem that I found in
> > real code.
> 
> The good news, is that if you really want to write this in C style, just
> write it in C and bind to it from OCaml.

I don't want to write it in C, as OCaml has considerable advantages.
In fact, the code was converted from C to gain these advantages
already.

> > The problem is that the return statement could be called from many
> > contexts, all with different types.  The compiler expects to unify all
> > these types (as the same type 'b) which is not possible.
> > 
> > It wasn't immediately clear to me if this was solvable.
> 
> I think you can define a generic return.

I'm not familiar with this, what is the "generic return"?

Rich.

-- 
Richard Jones

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-11-04 18:44           ` Richard W.M. Jones
  2017-11-04 18:48             ` SP
@ 2017-11-04 19:01             ` Max Mouratov
  2017-11-04 19:16             ` octachron
  2017-11-05 18:02             ` Petter A. Urkedal
  3 siblings, 0 replies; 44+ messages in thread
From: Max Mouratov @ 2017-11-04 19:01 UTC (permalink / raw)
  To: Richard W.M. Jones; +Cc: caml-list

Saturday, November 4, 2017, 11:44:01 PM, Richard wrote:
> The problem is that the return statement could be called from many
> contexts, all with different types.  The compiler expects to unify all
> these types (as the same type 'b) which is not possible.

See how it's done in Batteries:

type 'a t = 'a -> exn

let return label value =
  raise (label value)

let label (type u) (f : u t -> u) : u =
  let module M = struct exception Return of u end in
  try f (fun x -> M.Return x)
with M.Return u -> u


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-11-04 18:53               ` Richard W.M. Jones
@ 2017-11-04 19:03                 ` SP
  0 siblings, 0 replies; 44+ messages in thread
From: SP @ 2017-11-04 19:03 UTC (permalink / raw)
  To: caml-list

On 04/11/2017 18:53, Richard W.M. Jones wrote:
> I don't want to write it in C, as OCaml has considerable advantages.
> In fact, the code was converted from C to gain these advantages
> already.

Might be best to avoid that style then.

> I'm not familiar with this, what is the "generic return"?

One way is to make a module which has different signatures depending on
the module parameter. Then you can have different instances, like
String.c_return and Int.c_return. Also I think there are ways you can
make a function polymorphic, less tedious, but someone else might be
better covering those.

-- 
    SP

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-11-04 18:44           ` Richard W.M. Jones
  2017-11-04 18:48             ` SP
  2017-11-04 19:01             ` Max Mouratov
@ 2017-11-04 19:16             ` octachron
  2017-11-05 17:41               ` Richard W.M. Jones
  2017-11-05 18:02             ` Petter A. Urkedal
  3 siblings, 1 reply; 44+ messages in thread
From: octachron @ 2017-11-04 19:16 UTC (permalink / raw)
  To: caml-list

On 04/11/2017 19:44, Richard W.M. Jones wrote:
> The problem is that the return statement could be called from many
> contexts, all with different types.  The compiler expects to unify all
> these types (as the same type 'b) which is not possible.
This issue can be solved by making the type of return more precise, 
capturing the fact that return always raises:

     type 'a return = { return: 'b. 'a -> 'b } [@@unboxed]
     let with_return (type b) f =
       let exception Return of b in
       try f {return = (fun y -> raise (Return y))} with Return y -> y;;

It becomes then possible to write

     let f () =
       with_return (fun {return} ->
         if false then return "error";
         let a =
           match Some "abc" with
           | None -> return "another error"
           | Some a -> a in
         a
     )

— octachron.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-11-04 19:16             ` octachron
@ 2017-11-05 17:41               ` Richard W.M. Jones
  2017-11-05 18:39                 ` Yaron Minsky
  0 siblings, 1 reply; 44+ messages in thread
From: Richard W.M. Jones @ 2017-11-05 17:41 UTC (permalink / raw)
  To: octachron; +Cc: caml-list

On Sat, Nov 04, 2017 at 08:16:17PM +0100, octachron wrote:
> On 04/11/2017 19:44, Richard W.M. Jones wrote:
> > The problem is that the return statement could be called from many
> > contexts, all with different types.  The compiler expects to unify all
> > these types (as the same type 'b) which is not possible.
> This issue can be solved by making the type of return more precise,
> capturing the fact that return always raises:
> 
>     type 'a return = { return: 'b. 'a -> 'b } [@@unboxed]
>     let with_return (type b) f =
>       let exception Return of b in
>       try f {return = (fun y -> raise (Return y))} with Return y -> y;;
> 
> It becomes then possible to write
> 
>     let f () =
>       with_return (fun {return} ->
>         if false then return "error";
>         let a =
>           match Some "abc" with
>           | None -> return "another error"
>           | Some a -> a in
>         a
>     )

This one works great, thanks.

Rich.

-- 
Richard Jones

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-11-04 18:44           ` Richard W.M. Jones
                               ` (2 preceding siblings ...)
  2017-11-04 19:16             ` octachron
@ 2017-11-05 18:02             ` Petter A. Urkedal
  2017-11-05 18:24               ` Richard W.M. Jones
  3 siblings, 1 reply; 44+ messages in thread
From: Petter A. Urkedal @ 2017-11-05 18:02 UTC (permalink / raw)
  To: Richard W.M. Jones; +Cc: caml-list

I vouch for octachron solution to the lack of polymorphism in the
return function.

I tried to reformat the inspect_fs_unix_fstab.ml more along my own
coding style to get a feel for the issue:

https://gist.github.com/paurkedal/80b89c8fabe041e62eccc596d51f382b

What doesn't work with this style is falling though to the next block,
though I'm not sure that's I good for maintainability anyway.  This
is, however, even further away from the C style.

Petter

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-11-05 18:02             ` Petter A. Urkedal
@ 2017-11-05 18:24               ` Richard W.M. Jones
  2017-11-05 18:55                 ` Petter A. Urkedal
  0 siblings, 1 reply; 44+ messages in thread
From: Richard W.M. Jones @ 2017-11-05 18:24 UTC (permalink / raw)
  To: Petter A. Urkedal; +Cc: caml-list

On Sun, Nov 05, 2017 at 07:02:12PM +0100, Petter A. Urkedal wrote:
> I vouch for octachron solution to the lack of polymorphism in the
> return function.
> 
> I tried to reformat the inspect_fs_unix_fstab.ml more along my own
> coding style to get a feel for the issue:
> 
> https://gist.github.com/paurkedal/80b89c8fabe041e62eccc596d51f382b
> 
> What doesn't work with this style is falling though to the next block,
> though I'm not sure that's I good for maintainability anyway.  This
> is, however, even further away from the C style.

That appears to mainly play with indentation, which just means that
our tools won't work well.

FWIW here's the updated version I ended up with:

  https://gist.github.com/rwmjones/426821925fd1250096d7ddaac4103a12#file-gistfile1-txt-L57

This was formed by going back to the original C code:

  https://github.com/libguestfs/libguestfs/blob/5b74dd98a7926191cc085fc36be57f58bd6d80d8/lib/inspect-fs-unix.c#L1273

and rearranging the OCaml code to look more like it, adding return
statements to achieve this.

For those wondering why, the aim here is to translate the code from C
to OCaml as closely as possible (at first) in order to minimize the
inevitable bugs that will be added during the translation.  The C code
is very well tested over years.  I have plans to rework the code
completely later to make real use of OCaml, but first don't break
things.

Rich.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-11-05 17:41               ` Richard W.M. Jones
@ 2017-11-05 18:39                 ` Yaron Minsky
  2017-11-05 20:49                   ` Gabriel Scherer
  0 siblings, 1 reply; 44+ messages in thread
From: Yaron Minsky @ 2017-11-05 18:39 UTC (permalink / raw)
  To: Richard W.M. Jones; +Cc: octachron, caml-list

FWIW, this idiom is supported by Base.

https://github.com/janestreet/base/blob/master/src/with_return.mli

I notice we're not yet using the unboxed attribute, though, so we
should fix that...

y

On Sun, Nov 5, 2017 at 12:41 PM, Richard W.M. Jones <rich@annexia.org> wrote:
> On Sat, Nov 04, 2017 at 08:16:17PM +0100, octachron wrote:
>> On 04/11/2017 19:44, Richard W.M. Jones wrote:
>> > The problem is that the return statement could be called from many
>> > contexts, all with different types.  The compiler expects to unify all
>> > these types (as the same type 'b) which is not possible.
>> This issue can be solved by making the type of return more precise,
>> capturing the fact that return always raises:
>>
>>     type 'a return = { return: 'b. 'a -> 'b } [@@unboxed]
>>     let with_return (type b) f =
>>       let exception Return of b in
>>       try f {return = (fun y -> raise (Return y))} with Return y -> y;;
>>
>> It becomes then possible to write
>>
>>     let f () =
>>       with_return (fun {return} ->
>>         if false then return "error";
>>         let a =
>>           match Some "abc" with
>>           | None -> return "another error"
>>           | Some a -> a in
>>         a
>>     )
>
> This one works great, thanks.
>
> Rich.
>
> --
> Richard Jones
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-11-05 18:24               ` Richard W.M. Jones
@ 2017-11-05 18:55                 ` Petter A. Urkedal
  0 siblings, 0 replies; 44+ messages in thread
From: Petter A. Urkedal @ 2017-11-05 18:55 UTC (permalink / raw)
  To: Richard W.M. Jones; +Cc: caml-list

On 5 November 2017 at 19:24, Richard W.M. Jones <rich@annexia.org> wrote:
> That appears to mainly play with indentation, which just means that
> our tools won't work well.

Indeed.  I missed your motivation to keep this as close to the C code
as possible, as you explain:

> For those wondering why, the aim here is to translate the code from C
> to OCaml as closely as possible (at first) in order to minimize the
> inevitable bugs that will be added during the translation.  The C code
> is very well tested over years.  I have plans to rework the code
> completely later to make real use of OCaml, but first don't break
> things.

Petter

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-11-05 18:39                 ` Yaron Minsky
@ 2017-11-05 20:49                   ` Gabriel Scherer
  2017-11-05 21:48                     ` Yaron Minsky
  2017-11-05 21:53                     ` Petter A. Urkedal
  0 siblings, 2 replies; 44+ messages in thread
From: Gabriel Scherer @ 2017-11-05 20:49 UTC (permalink / raw)
  To: Yaron Minsky; +Cc: Richard W.M. Jones, octachron, caml-list, hugo heuzard

We also have return-by-local-exceptions in Batteries (the BatReturn
module), but reports from js_of_ocaml users (namely, Clément
Pit-Claudel) is that this style gets translated to extremely slow
Javascript code -- functions from Batteries using this style (string
search functions in particular) were a performance bottleneck on the
javascript backend. I fixed the issue by rewriting all uses of
BatReturn in Batteries libraries themselves.
Long-term, it would be better to have Javascript backends produce
better code on this, but I think it is rather difficult -- it is easy
to compile efficiently local exceptions that are raised in the same
basic block, but with_return takes a callback so you have to both
inline and specialize before you are within reach of the optimization.

On Sun, Nov 5, 2017 at 7:39 PM, Yaron Minsky <yminsky@janestreet.com> wrote:
> FWIW, this idiom is supported by Base.
>
> https://github.com/janestreet/base/blob/master/src/with_return.mli
>
> I notice we're not yet using the unboxed attribute, though, so we
> should fix that...
>
> y
>
> On Sun, Nov 5, 2017 at 12:41 PM, Richard W.M. Jones <rich@annexia.org> wrote:
>> On Sat, Nov 04, 2017 at 08:16:17PM +0100, octachron wrote:
>>> On 04/11/2017 19:44, Richard W.M. Jones wrote:
>>> > The problem is that the return statement could be called from many
>>> > contexts, all with different types.  The compiler expects to unify all
>>> > these types (as the same type 'b) which is not possible.
>>> This issue can be solved by making the type of return more precise,
>>> capturing the fact that return always raises:
>>>
>>>     type 'a return = { return: 'b. 'a -> 'b } [@@unboxed]
>>>     let with_return (type b) f =
>>>       let exception Return of b in
>>>       try f {return = (fun y -> raise (Return y))} with Return y -> y;;
>>>
>>> It becomes then possible to write
>>>
>>>     let f () =
>>>       with_return (fun {return} ->
>>>         if false then return "error";
>>>         let a =
>>>           match Some "abc" with
>>>           | None -> return "another error"
>>>           | Some a -> a in
>>>         a
>>>     )
>>
>> This one works great, thanks.
>>
>> Rich.
>>
>> --
>> Richard Jones
>>
>> --
>> Caml-list mailing list.  Subscription management and archives:
>> https://sympa.inria.fr/sympa/arc/caml-list
>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-11-05 20:49                   ` Gabriel Scherer
@ 2017-11-05 21:48                     ` Yaron Minsky
  2017-11-05 21:53                     ` Petter A. Urkedal
  1 sibling, 0 replies; 44+ messages in thread
From: Yaron Minsky @ 2017-11-05 21:48 UTC (permalink / raw)
  To: Gabriel Scherer; +Cc: Richard W.M. Jones, octachron, caml-list, hugo heuzard

Yeah, this is a general problem with exception-catching idioms. We
rand into effectively the same issue with respect to the Base's Map
and Set implementations, which are rather slow on JavaScript. We
haven't rewritten those to a more efficient style yet, though.

y

On Sun, Nov 5, 2017 at 3:49 PM, Gabriel Scherer
<gabriel.scherer@gmail.com> wrote:
> We also have return-by-local-exceptions in Batteries (the BatReturn
> module), but reports from js_of_ocaml users (namely, Clément
> Pit-Claudel) is that this style gets translated to extremely slow
> Javascript code -- functions from Batteries using this style (string
> search functions in particular) were a performance bottleneck on the
> javascript backend. I fixed the issue by rewriting all uses of
> BatReturn in Batteries libraries themselves.
> Long-term, it would be better to have Javascript backends produce
> better code on this, but I think it is rather difficult -- it is easy
> to compile efficiently local exceptions that are raised in the same
> basic block, but with_return takes a callback so you have to both
> inline and specialize before you are within reach of the optimization.
>
> On Sun, Nov 5, 2017 at 7:39 PM, Yaron Minsky <yminsky@janestreet.com> wrote:
>> FWIW, this idiom is supported by Base.
>>
>> https://github.com/janestreet/base/blob/master/src/with_return.mli
>>
>> I notice we're not yet using the unboxed attribute, though, so we
>> should fix that...
>>
>> y
>>
>> On Sun, Nov 5, 2017 at 12:41 PM, Richard W.M. Jones <rich@annexia.org> wrote:
>>> On Sat, Nov 04, 2017 at 08:16:17PM +0100, octachron wrote:
>>>> On 04/11/2017 19:44, Richard W.M. Jones wrote:
>>>> > The problem is that the return statement could be called from many
>>>> > contexts, all with different types.  The compiler expects to unify all
>>>> > these types (as the same type 'b) which is not possible.
>>>> This issue can be solved by making the type of return more precise,
>>>> capturing the fact that return always raises:
>>>>
>>>>     type 'a return = { return: 'b. 'a -> 'b } [@@unboxed]
>>>>     let with_return (type b) f =
>>>>       let exception Return of b in
>>>>       try f {return = (fun y -> raise (Return y))} with Return y -> y;;
>>>>
>>>> It becomes then possible to write
>>>>
>>>>     let f () =
>>>>       with_return (fun {return} ->
>>>>         if false then return "error";
>>>>         let a =
>>>>           match Some "abc" with
>>>>           | None -> return "another error"
>>>>           | Some a -> a in
>>>>         a
>>>>     )
>>>
>>> This one works great, thanks.
>>>
>>> Rich.
>>>
>>> --
>>> Richard Jones
>>>
>>> --
>>> Caml-list mailing list.  Subscription management and archives:
>>> https://sympa.inria.fr/sympa/arc/caml-list
>>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>>> Bug reports: http://caml.inria.fr/bin/caml-bugs
>>
>> --
>> Caml-list mailing list.  Subscription management and archives:
>> https://sympa.inria.fr/sympa/arc/caml-list
>> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>> Bug reports: http://caml.inria.fr/bin/caml-bugs

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Caml-list] What if exn was not an open type?
  2017-11-05 20:49                   ` Gabriel Scherer
  2017-11-05 21:48                     ` Yaron Minsky
@ 2017-11-05 21:53                     ` Petter A. Urkedal
  1 sibling, 0 replies; 44+ messages in thread
From: Petter A. Urkedal @ 2017-11-05 21:53 UTC (permalink / raw)
  To: Gabriel Scherer
  Cc: Yaron Minsky, Richard W.M. Jones, octachron, caml-list, hugo heuzard

On 5 November 2017 at 21:49, Gabriel Scherer <gabriel.scherer@gmail.com> wrote:
> We also have return-by-local-exceptions in Batteries (the BatReturn
> module), but reports from js_of_ocaml users (namely, Clément
> Pit-Claudel) is that this style gets translated to extremely slow
> Javascript code -- functions from Batteries using this style (string
> search functions in particular) were a performance bottleneck on the
> javascript backend. I fixed the issue by rewriting all uses of
> BatReturn in Batteries libraries themselves.
> Long-term, it would be better to have Javascript backends produce
> better code on this, but I think it is rather difficult -- it is easy
> to compile efficiently local exceptions that are raised in the same
> basic block, but with_return takes a callback so you have to both
> inline and specialize before you are within reach of the optimization.

Sounds like something a PPX rewriter could solve.  It could also avoid
the need to manually scope it, if we accept the module-level let as
the scope.

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2017-11-05 21:53 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-20  9:56 [Caml-list] What if exn was not an open type? Malcolm Matalka
2017-10-20 10:55 ` David Allsopp
2017-10-20 11:21   ` Ivan Gotovchits
2017-10-20 11:38     ` Simon Cruanes
2017-10-20 16:54       ` Malcolm Matalka
2017-10-20 19:47         ` Simon Cruanes
2017-10-21 21:15           ` Malcolm Matalka
2017-10-24 13:30       ` Richard W.M. Jones
2017-10-24 19:02         ` Petter A. Urkedal
2017-11-04 18:44           ` Richard W.M. Jones
2017-11-04 18:48             ` SP
2017-11-04 18:53               ` Richard W.M. Jones
2017-11-04 19:03                 ` SP
2017-11-04 19:01             ` Max Mouratov
2017-11-04 19:16             ` octachron
2017-11-05 17:41               ` Richard W.M. Jones
2017-11-05 18:39                 ` Yaron Minsky
2017-11-05 20:49                   ` Gabriel Scherer
2017-11-05 21:48                     ` Yaron Minsky
2017-11-05 21:53                     ` Petter A. Urkedal
2017-11-05 18:02             ` Petter A. Urkedal
2017-11-05 18:24               ` Richard W.M. Jones
2017-11-05 18:55                 ` Petter A. Urkedal
     [not found]         ` <CALa9pHQ-nhWf4T0U5gDiKTduPiEeXSZPQ=DY6N1YNbCXqRohPQ@mail.gmail.com>
2017-10-25  8:35           ` Richard W.M. Jones
2017-10-25  9:12             ` Philippe Veber
2017-10-25 14:52               ` Richard W.M. Jones
2017-10-25 16:37                 ` Ivan Gotovchits
2017-10-25 17:47                   ` SP
2017-10-26  8:06                 ` Malcolm Matalka
2017-10-26  8:11                   ` Xavier Leroy
2017-10-25 13:36             ` Ivan Gotovchits
2017-10-26  7:31             ` Petter A. Urkedal
2017-10-27 13:58             ` Oleg
2017-10-27 14:24               ` Philippe Veber
2017-10-27 14:49                 ` Leo White
2017-11-01  7:16                 ` Oleg
2017-11-04 17:52                   ` Philippe Veber
2017-10-20 17:07   ` Malcolm Matalka
2017-10-21 21:28 ` Nathan Moreau
2017-10-22 12:39   ` Malcolm Matalka
2017-10-22 13:08     ` Nathan Moreau
2017-10-24 11:11     ` SP
2017-10-24 11:16       ` Gabriel Scherer
2017-10-25 11:30         ` Malcolm Matalka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).