The term "shadow type system" has been used by such C++ luminaries as Herb
Sutter, Bjarne Stroustrup and Scott Meyers.

However, this is not the logical fallacy of appealing to authority.  It's an
observation that the very people who shaped the C++ language and added
exception declarations have themselves declared that it was a bad decision.
 The original designers have disowned the idea as being, ultimately, unfit
for purpose.

Amongst the problems they observed are:

- declarations give the false impression that they are the only Exceptions
that might be thrown.  I wonder How many programs have crashed because some
developer has diligently caught all the declared exceptions and therefore
didn't feel it necessary to write a handler for everything else.

- they give the impression that the compiler will always enforce that
they're caught.  James Iry's `chuck`, Java Puzzlers #43 and Lombok's
@SneakyThrows all demonstrate how this assumption can fail.


There was only positive thing that came out of C++... The ability to specify
you'll *never* throw an exception (the no-throw guarantee) has turned out to
be very useful for reasoning about the correctness/safety of a design.


On 23 September 2010 19:10, Reinier Zwitserloot <[email protected]> wrote:

> Why is it awkward? It keeps the API streamlined: You call fileOpen,
> and you get a FileHandle. When things do not proceed along the
> "essential path", you get an exception. Which is documented.
>
> Checked exceptions aren't any less useful just because "some people"
> decide to call it a "shadow type system" and interpret this to mean
> "shadow" is somehow "bad".
>
> On Sep 23, 1:02 pm, Kevin Wright <[email protected]> wrote:
> > Surely "having to care about it" is the whole point here!
> > isn't that the entire justification of *checked* exceptions... that they
> > force you to "care about it"?
> >
> > Either is an alternative way to insist upon such caring, and it has the
> > advantages of being composable and not perverting your type signatures.
> >
> > Think about this for a second: what's the signature of our fileOpen
> > function?
> > With checked exceptions it's: String => FileHandle (or maybe
> > FileNotFoundException)
> > With either it's: String => Either<FileHandle, Error>
> >
> > That bit in the parenthesis is awkward.  It's certainly a valid return
> from
> > the function, but if you use reflection to examine the return type then
> > you'll only see `FileHandle`.  It's like a wart on the side of the
> > signature, a return type that isn't a return type - this is why checked
> > exceptions are sometimes termed a "shadow type system".   This kind of
> > problem will definitely become more apparent once lambda support arrives
> in
> > Java.
> >
> > Then again... once lambda support arrives, we can use better solutions
> based
> > on the composability of functions.
> >
> > On 23 September 2010 11:11, Reinier Zwitserloot <[email protected]>
> wrote:
> >
> >
> >
> > > ... but you keep having to work around an "Either". This seems like a
> > > very bad idea, because now code I write has to care about it. After
> > > all, if I make a method that takes a String, I can't then call this
> > > method if I have an Either[String, Exception].
> >
> > > On Sep 23, 1:44 am, Josh Suereth <[email protected]> wrote:
> > > > You've completely neglected the composability of Either, which fail
> > > highly,
> > > > IMHO.
> >
> > > > Either[A,B] has a really really interesting use case if you can
> convert
> > > it
> > > > into a failure monad.   This allows you to chain operations as
> desired.
> >
> > > > // Assume every file operation returns an Either[Exception, T]
> > > > file.open.right.flatMap(doSomethingWithFile)
> >
> > > > This will return to us a Either[Exception, T] where T is the result
> type
> > > of
> > > > do something with File.    However I can continue to compose
> functions
> > > > together:
> >
> > >
> file.open.right.flatMap(doSomethingWithFile).right.flatMap(doSomethingElseW
> > > ithLastResult)
> >
> > > > This will also return a Either[Exception,T] where T is the result
> type of
> > > > doSomethingElseWithLastResult.
> >
> > > > The key here is that if an exception occurs after the first
> expression,
> > > the
> > > > rest of the function is not executed (similarly to exception
> handling).
> > > > However, I can pass the result of this code somewhere else, *without
> > > > handling the exception* and allow whoever is taking the
> > > Either[Exception,T]
> > > > to handle the exception as desired.    This means one piece of code
> can
> > > > create the Either and another that is *not necessarily in the same
> stack*
> > > > can handle it.   I could even pass the Either to another thread.
> >
> > > > Of course, this method of capture exceptions should not be used on
> > > actually
> > > > critical exceptions, like OOM or such, but it does give you a lot of
> > > > options.
> >
> > > > Also, the person who finally handles the exception has something
> which
> > > looks
> > > > like pattern matching.
> >
> > > > theResult match {
> > > >   case Right(value) =>  "Success!"
> > > >   case Left( t : FileNotFoundException) => "O NOES!!!"
> > > >   case Left( t : IOException) => "Something random happened in I/O,
> good
> > > > luck debugging it"
> >
> > > > }
> >
> > > > I think it's fair to say that this is more expressive than Java
> > > exceptions,
> > > > however they should *not* be used with actually critical exceptions.
>   In
> > > > any case, the Lift framework uses this concept to handle parameters
> and
> > > > parsing to great effect.   See Lift's Box
> > > > monad<
> > >http://blog.getintheloop.eu/2010/4/16/understanding-lift-s-box-t-monad
> >for
> > > > a good example of how this is useful.
> >
> > > > On Wed, Sep 22, 2010 at 6:20 PM, Reinier Zwitserloot <
> [email protected]
> > > >wrote:
> >
> > > > > .... but the either is noise when "file found" and "file not found"
> > > > > are NOT equally likely. There's no way to know as an API designer.
> The
> > > > > one thing you can tell is that "file found" is pretty much always
> > > > > going to be a reasonable option. No one is going to call fileOpen
> when
> > > > > they know for sure it'll fail, there wouldn't be any point. Your
> > > > > further comment that the "catch" will start drifting away makes no
> > > > > sense to me. Let's look at the either example again:
> >
> > > > > You're *calling a different method* to handle the actual result
> > > > > ("doSomethingWithFile"). If that's how we're going to handle it, we
> > > > > should be fair and let the try/catch example also use that. But,
> then
> > > > > the 'catch' for the fileOpen failure is NEVER going to drift away
> too
> > > > > far. If you're _not_ going to be calling a different method, the
> > > > > pattern matching version is going to make the case Right drift away
> > > > > just as far. This is yet another case where you see (and say, as if
> > > > > you're some sort of authority) that some way that java can't do is
> > > > > better, where its actually just personal preference.
> >
> > > > > Then there's "Left" and "Right" which are just ugly, and which also
> > > > > suggest there's only 1 type of exception that fileOpen can throw.
> try/
> > > > > catch does not suffer from any of these problems.
> >
> > > > > I don't understand why this thread has drifted into "try/catch
> itself"
> > > > > is bad. It started with "forcing onto a programmer the need to
> check
> > > > > certain exceptions based on method signatures is not a good idea"
> > > > > which most seem to agree with. That's entirely different from the
> idea
> > > > > that try/catch itself is bad.
> >
> > > > > On Sep 22, 2:34 pm, Kevin Wright <[email protected]> wrote:
> > > > > > Lets compare...
> >
> > > > > > Apologies for using Scala, my intent here is to demonstrate the
> > > > > differences
> > > > > > in the techniques using a language that supports both styles, not
> > > > > > specifically to advocate Scala.
> >
> > > > > >     val fileName = """c:\autoexec.bat"""
> >
> > > > > >     // using either
> > > > > >     fileOpen(fileName) match {
> > > > > >       case Left(handle) => doSomethingWithFile(handle)
> > > > > >       case Right(error) => logError(error)
> > > > > >     }
> >
> > > > > >    //using try/catch
> > > > > >     try {
> > > > > >       val handle = fileOpen(fileName)
> > > > > >       doSomethingWithFile(handle)
> > > > > >     } catch {
> > > > > >       case Exception(e) => logError(e)
> > > > > >     }
> >
> > > > > > The try/catch example has a couple of extra lines, but that's
> hardly
> > > > > > significant.  More importantly, as the amount of code grows
> between
> > > the
> > > > > try
> > > > > > and the catch, possible points of divergence for control flow
> become
> > > > > > increasingly unclear.  This is high-risk for
> > > > > > causing maintenance difficulties in the future.  using Either, on
> the
> > > > > other
> > > > > > hand, suggests that "file found" and "file not found" are equally
> > > valid
> > > > > > non-exceptional outcomes, and places them on a level footing as
> > > regards
> > > > > the
> > > > > > flow of control.
> >
> > > > > > On 22 September 2010 13:19, Ricky Clarkson <
> [email protected]
> >
> > > > > wrote:
> >
> > > > > > > The point is that it's your choice what to do.  Using Either
> does
> > > not
> > > > > mean
> > > > > > > you have to write lots of if statements, though you can if you
> > > like.
> >
> > > > > > > On Wed, Sep 22, 2010 at 12:22 PM, Miroslav Pokorny <
> > > > > > > [email protected]> wrote:
> >
> > > > > > >> How is either any better than letting catching an exception or
> > > letting
> > > > > the
> > > > > > >> code continue in the original spot. One gets a split off into
> a
> > > > > everythings
> > > > > > >> ok here a file, or jump to there and process the problem ?
> Using
> > > > > Either ends
> > > > > > >> up being "more" code because we get the branch for free with
> > > > > > >> exceptions...And given FileCreation failed is an exception the
> > > flow
> > > > > will be
> > > > > > >> most likely at least a bit different. Continuing on and
> checking
> > > later
> > > > > does
> > > > > > >> not seem to make much sense most of the time.
> >
> > > > > > >>  --
> > > > > > >> You received this message because you are subscribed to the
> Google
> > > > > Groups
> > > > > > >> "The Java Posse" group.
> > > > > > >> To post to this group, send email to
> [email protected].
> > > > > > >> To unsubscribe from this group, send email to
> > > > > > >> [email protected]<javaposse%[email protected]>
> <javaposse%2bunsubscr...@googlegroups .com>
> > > <javaposse%2bunsubscr...@googlegroups .com>
> > > > > <javaposse%2bunsubscr...@googlegroups .com>
> > > > > > >> .
> > > > > > >> For more options, visit this group at
> > > > > > >>http://groups.google.com/group/javaposse?hl=en.
> >
> > > > > > >  --
> > > > > > > You received this message because you are subscribed to the
> Google
> > > > > Groups
> > > > > > > "The Java Posse" group.
> > > > > > > To post to this group, send email to
> [email protected].
> > > > > > > To unsubscribe from this group, send email to
> > > > > > > [email protected]<javaposse%[email protected]>
> <javaposse%2bunsubscr...@googlegroups .com>
> > > <javaposse%2bunsubscr...@googlegroups .com>
> > > > > <javaposse%2bunsubscr...@googlegroups .com>
> > > > > > > .
> > > > > > > For more options, visit this group at
> > > > > > >http://groups.google.com/group/javaposse?hl=en.
> >
> > > > > > --
> > > > > > Kevin Wright
> >
> > > > > > mail / gtalk / msn : [email protected]
> > > > > > pulse / skype: kev.lee.wright
> > > > > > twitter: @thecoda
> >
> > > > > --
> > > > > You received this message because you are subscribed to the Google
> > > Groups
> > > > > "The Java Posse" group.
> > > > > To post to this group, send email to [email protected].
> > > > > To unsubscribe from this group, send email to
> > > > > [email protected]<javaposse%[email protected]>
> <javaposse%2bunsubscr...@googlegroups .com>
> > > <javaposse%2bunsubscr...@googlegroups .com>
> > > > > .
> > > > > For more options, visit this group at
> > > > >http://groups.google.com/group/javaposse?hl=en.
> >
> > > --
> > > You received this message because you are subscribed to the Google
> Groups
> > > "The Java Posse" group.
> > > To post to this group, send email to [email protected].
> > > To unsubscribe from this group, send email to
> >
> > ...
> >
> > read more »
>
> --
> You received this message because you are subscribed to the Google Groups
> "The Java Posse" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected]<javaposse%[email protected]>
> .
> For more options, visit this group at
> http://groups.google.com/group/javaposse?hl=en.
>
>


-- 
Kevin Wright

mail / gtalk / msn : [email protected]
pulse / skype: kev.lee.wright
twitter: @thecoda

-- 
You received this message because you are subscribed to the Google Groups "The 
Java Posse" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=en.

Reply via email to