<div dir="ltr">I do want to write for the record my reasons to prefer the Effect system approach in the hope to convince you and others about my view, but I do acknowledge that this discussion is still far, and the relevance of my words now may only appear when the work on patterns and string templates will finalize, so unless there is a good reason I will not continue the discussion further after this message.<div><br></div><div>Effect System enables a code style that is easier to follow, it hides the "unimportant" parts (unimportant to the logic) somewhere in the background and allows you to write as if there are no effects to your code (I am aware of the irony here). Of course it does in the end force you to handle the effects, but you can handle those effects orthogonally to your actual logic. Unlike the Monadic system which requires you to work in "the monad world" as described a lot by Haskell developers, you need to carry your Either wraps everywhere till you handle them.</div><div><br></div><div>In addition, I believe that there is another argument for the Effect system specifically for Java: there is a difference between a language feature and a datatype, unlike some other languages Java is built heavily over 3rd party libraries, if we look at the big libraries out there we would find that a lot of them are using custom Either (and friends) classes, this cause that composing those libraries is not as simple as we would want it to be, by making a language feature that handle those cases <i>well</i>, there will be a much larger intersection between the APIs (the "<i>well"</i>  in the previous sentence is important, I want to believe that it is possible to do that in Java)</div><div><br></div><div>Finally I want to link 2 more projects.</div><div><br></div><div>Apart from Koka there is also [Effekt](<a href="https://effekt-lang.org/">https://effekt-lang.org/</a>), I like the way Koka handles things better, but Effekt is another language that has Effects as its core mechanic.</div><div><br></div><div>Apart from Effect systems, there is also the idea of Coeffect systems, for a similar reasons as above, I really like a Coeffect type system and want to link to [my coeffect system in Java](<a href="https://github.com/Holo314/Coeffect">https://github.com/Holo314/Coeffect</a>) (I didn't have much time to work on it lately, but currently I am fighting Java's compiler plugins API to make it a stand alone plugin, as well as in the process of implementing custom type system in the annotation to enable stuff similar to what I wrote in my previous mail).</div><div><br></div><div>Again, I would love to discuss further when it is more relevant. </div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Mar 7, 2023 at 4:56 PM Brian Goetz <<a href="mailto:brian.goetz@oracle.com">brian.goetz@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

  
  <div>
    <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">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">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>On 3/7/2023 8:24 AM, Holo The Sage Wolf
      wrote:<br>
    </div>
    <blockquote type="cite">
      
      <div dir="ltr">
        <div>
          <p style="margin:0px 0px 1.2em">This is a
            continuation of this <a href="https://mail.openjdk.org/pipermail/amber-dev/2023-March/007849.html" target="_blank">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">I want to point to <a href="https://koka-lang.github.io/koka/doc/book.html#why-effects" target="_blank">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">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-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;white-space:pre-wrap;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248);display:block">
<span>@FunctionalInterface</span>
<span style="color:rgb(51,51,51);font-weight:bold">public</span> <span><span style="color:rgb(51,51,51);font-weight:bold">interface</span> <span style="color:rgb(68,85,136);font-weight:bold">EPredicate</span><<span style="color:rgb(68,85,136);font-weight:bold">T</span>, <span style="color:rgb(68,85,136);font-weight:bold">E</span> <span style="color:rgb(51,51,51);font-weight:bold">extends</span> <span style="color:rgb(68,85,136);font-weight:bold">Throwable</span>> </span>{
    <span><span style="color:rgb(51,51,51);font-weight:bold">boolean</span> <span style="color:rgb(153,0,0);font-weight:bold">test</span><span>(T t)</span> <span style="color:rgb(51,51,51);font-weight:bold">throws</span> E</span>;
}

<span>@FunctionalInterface</span>
<span style="color:rgb(51,51,51);font-weight:bold">public</span> <span><span style="color:rgb(51,51,51);font-weight:bold">interface</span> <span style="color:rgb(68,85,136);font-weight:bold">EConsumer</span><<span style="color:rgb(68,85,136);font-weight:bold">T</span>, <span style="color:rgb(68,85,136);font-weight:bold">E</span> <span style="color:rgb(51,51,51);font-weight:bold">extends</span> <span style="color:rgb(68,85,136);font-weight:bold">Throwable</span>> </span>{
    <span><span style="color:rgb(51,51,51);font-weight:bold">boolean</span> <span style="color:rgb(153,0,0);font-weight:bold">test</span><span>(T t)</span> <span style="color:rgb(51,51,51);font-weight:bold">throws</span> E</span>;
}

<span style="color:rgb(51,51,51);font-weight:bold">public</span> <span><span style="color:rgb(51,51,51);font-weight:bold">class</span> <span style="color:rgb(68,85,136);font-weight:bold">EStream</span><<span style="color:rgb(68,85,136);font-weight:bold">V</span>,<span style="color:rgb(68,85,136);font-weight:bold">E</span> <span style="color:rgb(51,51,51);font-weight:bold">extends</span> <span style="color:rgb(68,85,136);font-weight:bold">Throwable</span>> </span>{
    <span style="color:rgb(51,51,51);font-weight:bold">public</span> <EX extends Throwable> EStream<V, (E|EX)> filter(EPredicate<? <span style="color:rgb(51,51,51);font-weight:bold">super</span> T, (E|EX)> predicate) {
        ...
    }

    <span style="color:rgb(51,51,51);font-weight:bold">public</span> <EX extends Throwable> <span><span style="color:rgb(51,51,51);font-weight:bold">void</span> <span style="color:rgb(153,0,0);font-weight:bold">forEach</span><span>(EConsumer<? <span style="color:rgb(51,51,51);font-weight:bold">super</span> T, (E|EX)</span>> action) <span style="color:rgb(51,51,51);font-weight:bold">throws</span> E, EX </span>{
        ...
    }
}
</code></pre>
          <p style="margin:0px 0px 1.2em">Which allows you to
            have a fluent composition without losing the fine-grained
            checked exceptions:</p>
          <pre style="font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;white-space:pre-wrap;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248);display:block">
<span><span style="color:rgb(51,51,51);font-weight:bold">public</span> <span style="color:rgb(51,51,51);font-weight:bold">static</span> <span style="color:rgb(51,51,51);font-weight:bold">void</span> <span style="color:rgb(153,0,0);font-weight:bold">main</span><span>(string[] args)</span> <span style="color:rgb(51,51,51);font-weight:bold">throws</span> FileNotFoundException, IllegalAccessException, SQLException </span>{
    myEStream.filter(v -> ...) <span style="color:rgb(153,153,136);font-style:italic">// something that throws FileNotFoundException</span>
                     .filter(v -> ...) <span style="color:rgb(153,153,136);font-style:italic">// something that throws IllegalAccessException</span>
                     .forEach(v -> ...); <span style="color:rgb(153,153,136);font-style:italic">// something that throws SQLException</span>
}
</code></pre>
          <p style="margin:0px 0px 1.2em">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">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">I find this
            direction much nicer than using Either everywhere.</p>
        </div>
        <div><span>-- </span><br>
          <div dir="ltr">
            <div dir="ltr">Holo The Wise Wolf Of Yoitsu</div>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
  </div>

</blockquote></div><br clear="all"><div><br></div><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature"><div dir="ltr">Holo The Wise Wolf Of Yoitsu</div></div>