fixing infinities and ranges etc

[email protected] (Darren Duncan) Thu, 27 Oct 2016 21:57:24 -0700
Newsgroups perl.perl6.language
Message-ID <[email protected]>
I have observed that the current Perl 6 spec and implementations seem deficient 
in regards to representing some special values or conditions, in particular the 
concept of the two linear directional infinities or otherwise special values 
that naturally sort before and after everything else.

Moreover, some discussion I saw on the matter shows that these issues had been 
punted, so here I'm trying to propose a resolution or process to that end.

Here are some links for context:

* http://irclog.perlgeek.de/perl6/2014-08-20#i_9217322
* https://docs.perl6.org/type/Range#method_infinite
* https://github.com/rakudo/rakudo/blob/nom/src/core/Range.pm

Here are some proposals and comments:

1. I think the best way to represent various special values like this is as 
singleton types, basically in the same way various Failure or Exception are 
handled, such as the various X::Foo classes.  So for example, we should add 
X::NegInf and X::PosInf, or alternately per Larry's comment in the first link, 
something like X::BeforeEverything and X::AfterEverything or X::BE and X::AE. 
Actually we may want both the infs and the BE/AEs where distinguishing them is 
useful.  Similarly I recommend adding such singletons for various other math 
concepts such as X::DivByZero and X::ZeroToTheZero etc.

2. In the case of NegInf/PosInf (alternately read as BE/AE from now on), generic 
ordering sensitive operators like cmp would have signatures defined such as 
(NegInf, Any), there would be 4 combos of those, which would be defined to 
always return FALSE or TRUE as appropriate; as such, all values would be 
comparable with these singletons automatically.  Also, any dyadic min/max 
operators would use these singletons as their identity values.

3. Regular types such as Int or Rat or Str etc should be pure and just include 
normal values, that is just actual numbers for the numeric types etc.  Then, 
contexts that might produce or want to recognize failure conditions alternately 
accept or return the appropriate Failure singletons mentioned, as if a type 
union were defined over the regular types and the failure types; users can 
choose whether they want to allow the special values explicitly by either 
including or excluding them from signatures, so naming eg just Int will only 
accept actual numbers.

4. Independent of the above points, the current Range class has a problem in 
that it doesn't distinguish which endpoint is infinite.  Just as it currently 
distinguishes whether each endpoint is open or closed, it needs to distinguish 
whether each endpoint is infinite or finite.  All 4 of these cases need to be 
distinguished: 5..10, -Inf..10, 5..Inf, -Inf..Inf and I hope it should be 
self-evident why that is important.  For starters, it is completely valid to ask 
whether a value is in any of the given ranges; for half-infinite ranges, it is a 
generalized form for asking if the value is larger or smaller than the finite 
end; for fully-infinite ranges, the answer is always TRUE.  Another way to think 
about it is that a Range is just a concise way of expressing a set.  The current 
Range class simply has a boolean attribute that says is the Range infinite, yes 
or no, and that needs fixing.

5. A generic solution to representing Ranges properly is to use the two special 
singletons I mentioned be the endpoint values.  A lot of comparing operations 
would then just work.  Using the range to generate a list of member values would 
also work in some cases, depending where the infinities are and in what 
direction we are enumerating.

So what are the thoughts on this?  Can we get appropriate improvements into Perl 
6d and implementations etc?  Also, is any of what I said actually already done? 
  Certainly some key parts at least are not.

Thank you.

-- Darren Duncan