<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<font size="4"><font face="monospace">Thanks for the link to Koka.
<br>
<br>
Indeed, I spent many hours prototyping something exactly like
this for Streams back in the Java 8 days, as an extension to one
of the "exception transparency" proposals that came up at the
time. As you point out, in libraries like streams, a throwing
lambda passed as a parameter "pollutes" the type of the returned
stream, since the lambda is incorporated into the stream and may
be invoked by a later operation, and therefore might be thrown
from that later operation. <br>
<br>
This basically asks the generic type system to have type
variables to track effects as well as types (see, e.g., "Type
and Effect Systems", Nielsen and Nielsen.) <br>
<br>
As your example shows, it is possible to do this with (a) some
form of variadic generics and (b) some algebraic operations on
variadic parameters (e.g., concatenating, unioning,
differencing). It also means that generic classes like Stream
have to carry around additional type variables describing their
exceptions (effects), and those tvars are "different" from
ordinary tvars. <br>
<br>
Our conclusion at the time we did this experiment is that, while
the approach is viable, annotation burden on library authors is
high, and this burden flows through to clients as well. (Even
if we allow use sites to elide the exception information, so
they can say Stream<String> rather than Stream<String,
ExceptionGoop>, it still flows into the docs and error
messages.) It also makes generics "even more complex" (and
people still complain generics are too complex.) <br>
<br>
So the outcome of this experiment was "yes, it can be made to
work, but no, we don't think putting into Java at this time is
likely to be seen entirely positively."<br>
<br>
<blockquote type="cite">
<p style="margin:0px 0px 1.2em!important">While I do believe
that the actual solution will require much more thought than
this (e.g. deconstruction of generic sums to be able to
handle specific exceptions and remove those exceptions from
the final union type of exceptions), this is a showcase that
a nice and composable checked exceptions works even without
Monadic types.</p>
</blockquote>
<br>
Indeed. The need for asymmetric difference as one of the
algebraic operations on effect variables is one of those
surprises that bites you the first time you encounter it. <br>
<br>
<blockquote type="cite">
<p style="margin:0px 0px 1.2em!important">I find this
direction much nicer than using Either everywhere.</p>
</blockquote>
<br>
I am not sure whether I do or not, which is one reason we've not
done either yet...<br>
<br>
<br>
</font></font><br>
<div class="moz-cite-prefix">On 3/7/2023 8:24 AM, Holo The Sage Wolf
wrote:<br>
</div>
<blockquote type="cite" cite="mid:CAKswmE7-=O-a2UH753TgxEzg7jX-0TMWLasqOZvLaaH3rbuMHw@mail.gmail.com">
<div dir="ltr">
<div class="markdown-here-wrapper" style="">
<p style="margin:0px 0px 1.2em!important">This is a
continuation of this <a href="https://mail.openjdk.org/pipermail/amber-dev/2023-March/007849.html" moz-do-not-send="true">thread</a>, unfortunately I only
joined the mailing list, so I can’t reply to it so I
apologize for opening a new thread.</p>
<p style="margin:0px 0px 1.2em!important">I want to point to <a href="https://koka-lang.github.io/koka/doc/book.html#why-effects" moz-do-not-send="true">Koka</a>, Koka is a language built
upon the concept of Effect, a generalization of how Java
treats checked exceptions (and similarly to what Brian Goetz
said about how Checked exceptions are equivalent to Either,
general Effect system is equivalent to full monadic type
system).</p>
<p style="margin:0px 0px 1.2em!important">The language is very
interesting and worth reading about, but the relevant part
is their Polymorphic Effects, which allow you to extend the
effects. In Java pseudo code, it means that the following is
valid:</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code class="hljs language-java" style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248)">
<span class="hljs-annotation">@FunctionalInterface</span>
<span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">interface</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">EPredicate</span><<span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">T</span>, <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">E</span> <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">extends</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">Throwable</span>> </span>{
<span class="hljs-function"><span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">boolean</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">test</span><span class="hljs-params">(T t)</span> <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">throws</span> E</span>;
}
<span class="hljs-annotation">@FunctionalInterface</span>
<span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">interface</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">EConsumer</span><<span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">T</span>, <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">E</span> <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">extends</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">Throwable</span>> </span>{
<span class="hljs-function"><span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">boolean</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">test</span><span class="hljs-params">(T t)</span> <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">throws</span> E</span>;
}
<span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">class</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">EStream</span><<span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">V</span>,<span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">E</span> <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">extends</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">Throwable</span>> </span>{
<span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">public</span> <EX extends Throwable> EStream<V, (E|EX)> filter(EPredicate<? <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">super</span> T, (E|EX)> predicate) {
...
}
<span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">public</span> <EX extends Throwable> <span class="hljs-function"><span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">void</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">forEach</span><span class="hljs-params">(EConsumer<? <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">super</span> T, (E|EX)</span>> action) <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">throws</span> E, EX </span>{
...
}
}
</code></pre>
<p style="margin:0px 0px 1.2em!important">Which allows you to
have a fluent composition without losing the fine-grained
checked exceptions:</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code class="hljs language-java" style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248)">
<span class="hljs-function"><span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">public</span> <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">static</span> <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">void</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">main</span><span class="hljs-params">(string[] args)</span> <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">throws</span> FileNotFoundException, IllegalAccessException, SQLException </span>{
myEStream.filter(v -> ...) <span class="hljs-comment" style="color:rgb(153,153,136);font-style:italic">// something that throws FileNotFoundException</span>
.filter(v -> ...) <span class="hljs-comment" style="color:rgb(153,153,136);font-style:italic">// something that throws IllegalAccessException</span>
.forEach(v -> ...); <span class="hljs-comment" style="color:rgb(153,153,136);font-style:italic">// something that throws SQLException</span>
}
</code></pre>
<p style="margin:0px 0px 1.2em!important">This also makes the
type system of the <code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">throws</code>
clause a subset of the generics type system.</p>
<p style="margin:0px 0px 1.2em!important">While I do believe
that the actual solution will require much more thought than
this (e.g. deconstruction of generic sums to be able to
handle specific exceptions and remove those exceptions from
the final union type of exceptions), this is a showcase that
a nice and composable checked exceptions works even without
Monadic types.</p>
<p style="margin:0px 0px 1.2em!important">I find this
direction much nicer than using Either everywhere.</p>
</div>
<div><span class="gmail_signature_prefix
markdown-here-signature">-- </span><br>
<div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">
<div dir="ltr">Holo The Wise Wolf Of Yoitsu</div>
</div>
</div>
</div>
</blockquote>
<br>
</body>
</html>