Hacker News new | past | comments | ask | show | jobs | submit login

I find the idea of being able to specify numerical types with arbitrary ranges very appealing.

In Pascal these are called range types, e.g.

month: 1..12

would define an integer where the type system would ensure that it is always between 1 and 12.

Apart from Ada this seems to be an alien concept to all other languages. The concept of a "range type" also seems to have other meanings.

What is the Pascal "range type" properly called in type theory and what is its relationship to refinement types?






Nim calls these subranges https://nim-lang.org/docs/manual.html#types-subrange-types

  Subrange = range[0..5]
  PositiveFloat = range[0.0..Inf]

Ranges are awfully useful in Ada, but a very small help in dimensionality/units analyis.

If you mean to go all the way on units, dimensions and typing, there's a bestiary there, quited maintained (with several Ada 'takes' too) https://www.gmpreussner.com/research/dimensional-analysis-in...


Anybody correct me if I'm wrong -- in Pascal these subranges can specify the size of the variable in memory and check compile-type assignment to a literal value, but don't (can't) do much else.

There's the concept of dependent types in e.g. Idris which lets us correctly do this sort of range check throughout the program (not just on literal assignment) but it comes with strict requirements on what the compiler can allow, such as no unbounded recursion, because checking dependent types is roughly equivalent to running the program.


it is a refinement type over the base number type, where the predicate constrains the number to lie in an interval

e.g. { x:Int8 | 1 ≤ x ≤ 12 }


I frequently wish I had a natural number type. So many programs would benefit from the type system guaranteeing that numbers are never negative.

Nim has Natural and Positive (signed int) types that checked at compile and runtime. You can also define arbitrary range types for any ordinal type, for example enums:

  type
    Month = enum Jan, Feb, Mar, Apr, May, ...
    SpringMonth = range[Mar..May]
  
  var m: SpringMonth = Mar
It will raise under/overflow exception if value falls out of range.

Rust has this one - though the ergonomics are a little awkward. Its called NonZero:

https://doc.rust-lang.org/std/num/type.NonZeroU32.html


Easy enough to write in some languages... as long as you only need to support addition and multiplication, or a very limited set of numbers.

I’ve seen “month” being implemented in typescript as a big sum type ‘1 | 2 | 3 | … | 12’ :) probably ranges could just be syntactical sugar on top of that, but I suppose it probably causes big inefficiencies for the compiler

raku has "type subsets" which can do this (and more)

https://docs.raku.org/language/typesystem#subset


> an integer where the type system would ensure that it is always between 1 and 12

How does Pascal handle overflow/underflow? E.g. Month 10 + Month 11 = Month 21?


Uh, seemingly, yeah. 10+11 = 21. No bounds checking on addition or assignment.

https://onlinegdb.com/3KhhaReLV


I assume modulo?

Haskell calls it Ord, for ordinal. https://en.m.wikipedia.org/wiki/Ordinal_data_type

Haskell's Ord typeclass is for ordering; it just represents types that have a total order, it doesn't represent ranges.

My bad the ordinal data type class is Enum not Ord!



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: