10

Everyone knows the elegant way to express natural numbers on dependently typed functional languages:

data Nat = Zero | Succ Nat

Integer, Fraction, Real, Complex and Quaternion are, too, very important for practical programming application. One could implement them as:

data Integer    = Integer (sign : Bool) (modulus : Nat)
data Fraction   = Fraction (dividend : Nat) (divisor : Nat)
data Real       = Real (exponent : Integer) (fraction : Nat)
data Complex    = Complex Real Real
data Quaternion = Quaternion Real Real Real Real

But none of those really reflect the actual structure/nature of their types as meaningfully as Nats do. Integer isn't isomorphic to actual integers, for example (as Zero occurs twice). Reals needs more than a million of cells to store (3.141592), yet not even 100 to store (4096), which looks unbalanced. Complex is just a tuple of Reals, which doesn't really reflect what a Complex is. I wonder what is the natural, elegant way to express the numeric tower on functional programming languages?

MaiaVictor
  • 51,090
  • 44
  • 144
  • 286
  • I've asked similar questions before but I think nobody ever came with a good enough solution. – MaiaVictor Dec 10 '15 at 17:32
  • 7
    Why don't you think that "accurately reflects what a `Complex` is"? (That said, your `Real` only includes finitely long decimal values, which is a strict subset of the rationals.) I mean, I suppose you could represent it as the real polynomials mod x^2 + 1, but it's not clear to me what your objection is. – Louis Wasserman Dec 10 '15 at 17:38
  • 2
    Mathematically speaking, there is no "fundamental structure" of anything other than what we pick, and if we like we can show two different structures are equivalent and use them interchangeably. There's nothing unmathematical about your representation of the integers. – Louis Wasserman Dec 10 '15 at 17:40
  • The point is, I just came with those types of nowhere with no mathematical background or real understanding of how those numbers work. I think it is pretty safe to assume that there are better representations than my sketchy solution, so I'm asking what people with greater mathematical knowledge came up with. – MaiaVictor Dec 10 '15 at 17:41
  • 4
    Also, structures, even if truly isomorphic, matter for performance and ease of use, for example. I could encode natural numbers as `data Nat = Add Nat Nat | FloorHalf Nat | Two | Zero`, but implementing algebraic algorithms on that would be terribly messy. It is quite clear that isn't a good representation of Nats. I think the same could be said about my arbitrary encodings... – MaiaVictor Dec 10 '15 at 17:46
  • 6
    I think you'll tend to find that performance and mathematical elegance are conflicting goals. You might start by representing naturals in binary, e.g. with `[Bool]`, but it's not really clear what you're going for. – Louis Wasserman Dec 10 '15 at 17:51
  • Louis, I'll be happy if you just point me to links where I can read about different, better thought encodings of numbers whatever the reason is for. I just want to learn, do we really need to complicate that request so much? My goal is mostly mathematical elegance. – MaiaVictor Dec 10 '15 at 17:54
  • The problem with this question is that "natural" and "elegant" are too subjective. I think it is perfectly natural and elegant to define the set of integers as the union of the set of non-negative integers (Nat) and the additive inverse of that set, which corresponds closely to your encoding of `Integer`. An objective measure is something like "I need a representation of numbers that will be performant in this particular scenario" or "I need a representation of numbers which will allow me to encode these properties about the numbers in the type system" or something of the sort. – user2407038 Dec 10 '15 at 18:00
  • Can you just disregard the question and point me to a few interesting resources on numeric encodings that are interesting for you? If I just have some suggestions and pointers that will be already of great help. – MaiaVictor Dec 10 '15 at 18:02
  • 5
    You might want to read a bit about homotopy type theory. Heavy stuff, but it gets deeply into the whole issue of non-unique representations. – dfeuer Dec 10 '15 at 18:04
  • @dfeuer I've asked on the #haskell channel those days if there is any resource on HoTT aimed to people without mathematical backgrounds, or, at least, a roadmap for a person without such towards HoTT. I think nobody answered, though. Or I forgot to ask. Don't remember... – MaiaVictor Dec 10 '15 at 18:05
  • Let me know if you find one; I know nothing about type theory myself. – dfeuer Dec 10 '15 at 18:07
  • 2
    Agda's [`Integer`](https://github.com/agda/agda-stdlib/blob/master/src/Data/Integer/Base.agda#L28) doesn't contain two zeros. [Here](https://hal.inria.fr/hal-00806920v1/document) is a survey about constructive reals. To study HoTT, you first need to study ITT, since HoTT = ITT + univalence + HITs. If you're comfortable with ITT, then the HoTT book should be comprehensible (I've read just a few chapters, though). – effectfully Dec 10 '15 at 19:22
  • Thanks, @user3237465, that kind of link is what I'm always looking for. What would you suggest to study ITT? Also, why ITT, not CoC? I thought it was regarded as a better system? – MaiaVictor Dec 10 '15 at 19:33
  • 1
    @Viclib, CoC is a weak system as it contains only `Prop`. CIC has a proper hierarchy of universes as well as ECC (an Extended Calculus of Constructions), which is a mix of CoC and stratified MLTT. Add inductive data types to ECC and you'll get UTT (Unified Type Theory). And there is also [PiSigma](http://www.andres-loeh.de/PiSigma/PiSigma.pdf). All these are ITTs (Intensional Type Theory) and it doesn't matter much which to study, as they all are very similar. I'd suggest to study an implementation of a type theory like Agda or Idris, but I don't have any good introductions on top of my head. – effectfully Dec 10 '15 at 20:03
  • I see. But where do I learn about them deep enough? What is there to learn, anyway? I guess I've successfully implemented coc at this point so I kinda know how it works. But knowing why it works, what can be done with it, or how I'd use it to prove things... is another level... – MaiaVictor Dec 10 '15 at 20:47
  • 1
    Well, Nat is isomorphic to the integers and rational numbers on its own, because all three are countably infinite types. For reals, you need something else however. You might want to look the Cauchy sequence and continued fraction representations of reals. – David Young Dec 10 '15 at 23:38
  • 3
    Here's a video about how you might implement those real number representations in Haskell: https://m.youtube.com/watch?v=LJQgYBQFtSE – David Young Dec 10 '15 at 23:47
  • I was actually thinking of that video when I asked the question. The fact you posted it kinda shows how scarce is the published content on the matter... – MaiaVictor Dec 11 '15 at 00:48
  • 2
    @Viclib, I'd study [these](https://github.com/pigworker/CS410-14) Conor McBride's lectures notes, perhaps. – effectfully Dec 11 '15 at 09:40

1 Answers1

0

I realize this is an old question and my answer is in Scala rather than Haskell/Idris, but it could be interesting to see how they do it in Spire. The approach there is to establish a hierarchy of algebraic structures (i.e., Semigroup/Group/Ring/Field/etc.) first and then instantiate numeric types on top of those, adding various algorithms from numerical methods. I'm sure one could find some useful ideas in there.