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