<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <font size="4" face="monospace">Error handling is hard, no matter
      how you slice it.  (See
      <a class="moz-txt-link-freetext" href="https://joeduffyblog.com/2016/02/07/the-error-model/">https://joeduffyblog.com/2016/02/07/the-error-model/</a> for a mature
      analysis of all the options.)  <br>
      <br>
      The benefit of using algebraic data types (e.g., the Either or Try
      monads) for error handling is _uniformity_.  Type systems such as
      the simply typed lambda calculus (Peirce, Ch9) say that if we have
      types T and U, then the function type `T -> U` is also a type. 
      Such function types are well behaved, for example they can be
      composed: if f : T -> U and g : U -> V, then g.f : T ->
      V.  <br>
      <br>
      A Java method <br>
      <br>
          static int length(String s)<br>
      <br>
      can be viewed as a function String -> int.  But what about a
      Java method <br>
      <br>
          static int parseInt(String s) throws NumberFormatException<br>
      <br>
      ?  This is a _partial function_; for some inputs, parseInt() does
      not produce an output, instead it produces an effect (throwing an
      exception.)  Type systems that describe partial or effectful
      computations are significantly more complicated and less
      well-behaved.  <br>
      <br>
      Modeling a division result as in the following Haskell data type:<br>
      <br>
          data DivResult = Success Double | Failure<br>
      <br>
      means that arithmetic operations are again total:<br>
      <br>
          DivResult divide(double a, double b)<br>
      <br>
      This has many benefits, in that it becomes impossible to ignore a
      failure, and the operation is a total function from double x
      double to DivResult, rather than a partial function from double x
      double to double.  One can represent the success-or-failure result
      with a single, first-class value, which means I can pass the
      result to other code and let it distinguish between success and
      failure; I don't have to deal with the failure as a side-effect in
      the frame or stack extent in which it was raised.  The common
      complaints about "lambdas don't work well with exceptions" comes
      from the fact that lambdas want to functions, but unless their
      type (modeled in Java with functional interfaces) accounts for the
      possibility of the exception, we have no way to tunnel the
      exception from the lambda frame to the invoking frame.  <br>
      <br>
      It is indeed true that exceptions carry more information, and that
      information comes at a cost -- both a runtime cost (exceptions are
      expensive to create and have significant memory cost) and a
      user-model cost (exceptions are constraining to deal with, and
      often we just throw up our hands, log them, and move on.)  On the
      other hand, algebraic data types have their own costs -- wrapping
      result success/failure in a monadic carrier intrudes on API types
      and on code that consumes results.  <br>
      <br>
      Error handling is hard, no matter how you slice it.<br>
    </font><br>
    <div class="moz-cite-prefix">On 12/4/2023 7:05 PM, David Alayachew
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAA9v-_O05VLWg6BAqCc0PjX+npzYRGCn=v4YoGrq+7mJXrdxfw@mail.gmail.com">
      
      <div dir="ltr">
        <div class="gmail_default" style="font-family:monospace">Hello
          Amber Dev TeaM,</div>
        <div class="gmail_default" style="font-family:monospace"><br>
        </div>
        <div class="gmail_default" style="font-family:monospace">I
          learned a lot about Exceptions in the previous discussion
          above, so I figured I'd ask this question as well -- when does
          it make sense to handle exceptional cases via a Sealed Type
          (DivisionResult ====> Success(double answer) ||
          DivideByZero()) vs an Exception (DivideByZeroException)?</div>
        <div class="gmail_default" style="font-family:monospace">
          <div dir="ltr">
            <div class="gmail_default" style="font-family:monospace"><br>
            </div>
            <div class="gmail_default" style="font-family:monospace">The
              only difference I can see is that an Exception gives you
              debugging details (line number, stack trace) that would be
              very difficult for a Sealed Type to attain. And if that is
              the key difference, doesn't that sort of imply that we
              should opt into the more info-rich source of information
              wherever possible? After all, debugging is hard enough and
              more info is to everyone's benefit, right?</div>
            <div class="gmail_default" style="font-family:monospace"><br>
            </div>
            <div class="gmail_default" style="font-family:monospace">And
              most of the extra info is static (line numbers don't
              change). I'll avoid performance as a reason, as I don't
              understand the mechanics of what makes one faster or
              slower.</div>
            <div class="gmail_default" style="font-family:monospace"><br>
            </div>
            <div class="gmail_default" style="font-family:monospace">Thank
              you all for your time and help!</div>
            <div class="gmail_default" style="font-family:monospace">David
              Alayachew<br>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>