Abacist – Calculations with non-decimal units and mixed bases in Scala

34 pointsposted 10 months ago
by cbeach

6 Comments

btbuildem

10 months ago

OP you may have meant to have linked directly to https://soundness.dev/abacist

Not a scala person, but I like the idea of being able to shift between unit/measurement systems. Lots of strange little edge cases. Eg, how does rounding work in imperial, can I get 3.1415926535 meters to the closest 1/64th of an inch?

cbeach

10 months ago

ah that's strange - I thought I had linked correctly. And now it's too late to edit :-(

TOGoS

10 months ago

This seems similar to the 'ComplexAmount' system I used to use in PHP and JavaScript programs for representing measurements using mixed units. Basically just a map of unit code => quantity. And for extra exactness, quantity would be represented as a rational number.

Was useful for a client that let you place orders using a mixture of USD and CAD (the alternative being a lot of 'canada'/'canadian'/'cad' fields added willy-nilly everywhere a cost needed to be represented; I don't know how people can stand to program that way). But also for generating G-code for a CNC router [1], when sometimes you want to model in mm, and sometimes in inches, and keep all the numbers exact until the last possible moment.

[1] https://github.com/TOGoS/TTSGCG

nadavwr

10 months ago

PHP and JavaScript are dynamic. Here you'll be able to pass distances as feet or meters, but if you try to pass in pounds you'll get a compile time error -- can't do that in dynamic languages :)

TOGoS

10 months ago

So, when I said JavaScript, I really meant TypeScript, and I found its gradual/structural typing system to be the most ergonomic type system I've ever used (if you want nominal types, it's pretty trivial to get there just by adding a compile-time-only tag, like `{ typeName?: "FooType" }`).

In this case, the TypeScript approach might be something like

  const distanceInMm : {"mm": Rational} = toMm(distanceInArbitraryUnits);
You can get as specific as you want, without having to wrap/unwrap anything, or even define a new named type. [1]

I think I like Scala conceptually--when people talk about it I think "yeah, good idea!"--but every time I've looked at Scala code it struck me as having an excessive amount of boilerplate to wrap/unwrap stuff just to make the type checker happy.

The other bad-tasting thing about Scala is that I wrote a program[2] in it many years ago and then later came back to try to fix some bugs and the language had changed so much that I had to find some old version of it + an old JVM and Dockerize it. Docker's a godsend for this sort of thing, but kind of inconvenient for development.

[1] My notes about this approach in TypeScript: https://www.nuke24.net/plog/32.html

[2] https://github.com/TOGoS/PicGrid