3 ms·
Does this matter any more than the fact the underlying representation within sin is e.g. an 80 bit number no programming language can give you? `Angle` is a bad
by morelisp 4y ago
Does this matter any more than the fact the underlying representation within sin is e.g. an 80 bit number no programming language can give you? `Angle` is a bad name for this example because a newtype should be named after the unit rather than what it models, but once you've newtyped it, what matters is that you call sin with the right one, not the actual representation.
- munificent 4y agoYes, the entire point of the article is that it does in fact matter. > what matters is that you call sin with the right one, not the actual representation. No, the actual representation does matter. At some point, arithmetic operations are being performed and those operations consume CPU cycles. If you care about the performance of the code, you care about having a representation that minimizes the number of those operations.
- morelisp 4y agoSo make sure you use `typeof sin[0]` or whatever the syntax is in your language for your own variables - in the end this still requires newtyping the thing. For performance in this context, the actual representation does not matter - only that your code and your sin code agree to avoid the conversion cost.
- munificent 4y agoI think you're confusing "representation" to mean just the number of bits allocated to the number, but the article and my comments also use it to mean what the numeric range of those values represents (hence "representation"). How that's modeled in the static type system is completely orthogonal to the underlying arithmetic operations that are performed and their efficiency. The article is entirely about the latter.
- morelisp 4y agoNo, I think you're confused about what I'm saying about performance. I definitely don't think "representation" just means the number of bits. > How that's modeled in the static type system is completely orthogonal to the underlying arithmetic operations that are performed and their efficiency. No! A type system gives information in in both directions. Normally yes, we use it to impose some interpretation on a representation to produce a value, so we can think in values and not bits. But if two types model the same range of entities, i.e. angular measurements, it also tells you if you have a value with a representation that you might have to spend time futzing with to integrate with something else expecting the same entity but a different type. If we had reasonable types, sin could define the type it wants to do what it does efficiently (turns, or radians if the platform has an efficient instruction, or a lookup table index into some division of a quadrant, or whatever). That representation matters to the sin author, but not the user. All the user cares about is, then, how many times do I have to pay some conversion cost? And if I'm using the type the sin author provided, the answer is zero (or maybe like one, at initial load). But that relies on the sin author using such a newtype. (Arguably the user also cares how much memory it takes to store the representation the sin author chose, but in practice for sin that's going to be a word or less whatever the representation is.) You also have a blinkered view of the article if you think it's "entirely about" performance, given how often it also talks about simplicity and accuracy.
- munificent 4y agoI feel like we're talking past each other or the goal posts are moving or something. > If we had reasonable types, sin could define the type it wants to do what it does efficiently (turns, or radians if the platform has an efficient instruction, or a lookup table index into some division of a quadrant, or whatever). That representation matters to the sin author, but not the user. All the user cares about is, then, how many times do I have to pay some conversion cost? And if I'm using the type the sin author provided, the answer is zero (or maybe like one, at initial load). But that relies on the sin author using such a newtype. Everything here is equally true if you take types entirely out. sin() will ultimately be doing math on floating point values. The sin() function expects angles according to a specified scale. Some scales (turns, according to the author) require one less multiplication in the function prelude. Therefore, sin() is faster if it specifies that as the input scale. That benefit is negated if angles are stored in another scale and rescaled every time sin() is called. That's just hoisting the multiplication out to every callsite. So what you need is to store angles in the numeric scale that is fastest for the implementation of sin(). Whether those floating point angles are wrapped in a newtype is completely orthogonal. What matters is that the numeric scale you use to store and represent angles is the one that requires the least arithmetic in the underlying implementation of the trig functions. Unit types are great, but they solve different problems than the article is talking about.