14 ms·
Show HN: Numbat – A programming language with physical dimensions as types
- jqpabc123 3y agoperform computations with physical units. It has units awareness --- not necessarily only physical units. For example; light, temperature and time are measured in units but they are not physical units --- aka 3 dimensional.
- gus_massa 3y agoAll are physical units. In particular in special relativity time is couples with position and you myst use cuadrivectors (t, x, y, z).
- jqpabc123 3y agoTime exists independent of location and can not be visualized in any "physical" way. The same is true for lots of other units of measure. https://phys.org/news/2012-04-physicists-abolish-fourth-dimension-space.html https://phys.org/news/2012-04-physicists-abolish-fourth-dime...
- davidcuddeback 3y agoPhysical can be understood to mean "of or relating to matter and energy or the sciences dealing with them, especially physics." Light, temperature, and time are described by physics, so I would consider "physical" to be an accurate adjective for those units. You seem to be using a more limited definition of physical, closer to the word "spatial." Also, btw, you might want to read the article you linked. The article is discussing a fringe idea that some scientists have. Scientists are free to explore new ideas, and they make for good click bait for science journalists. Until those ideas gain traction, they don't provide for compelling arguments, though.
- gus_massa 3y agoThat paper is not good. I Special Relativity you have many cuadrivectors, for example: * time-space (t, x, y, z) * energy-omentum (E, px, py, pz) * Electromagnetic Potencial (V, Ax, Ay, Az) and even a few 4x4 matices like the electric and magnetic fields together. All of them change with the same equations. You can't break (t, x, y, z) and keep all the other. And there are extensions to particle physics that mix Special Relativity and Quantum Mechanics that use the same equations, and they have an agreement of theory and experiment of 8 digits. You can't break (t, x, y, z) and keep all the other! Also, the paper is published in a journal I never heard about. It's impossible to be sure, but it has a lot of single author articles that is a big red flag, and the titles of the other articles are too weird (Nobel price or crackpot, nothing in between).
- Aspos 3y agoThis is great. I want this as an addon to JS and Python.
- seanos 3y agoFor Python, there is the Pint library: https://pint.readthedocs.io/en/stable/ https://pint.readthedocs.io/en/stable/
- jsiva 3y agoAnother python alternative that work well with numpy arrays is astropy.units (also mentioned on the pint website): https://docs.astropy.org/en/stable/units/ https://docs.astropy.org/en/stable/units/
- evntdrvn 3y agoI can't resist mentioning F# Units of Measure aka UoM :) https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/units-of-measure https://learn.microsoft.com/en-us/dotnet/fsharp/language-ref...
- stiiv 3y agoThank you for not resisting. F# is very hard to beat for a tight domain model.
- openquery 3y agoAnd the equivalent uom in Rust. https://crates.io/crates/uom https://crates.io/crates/uom
- deleted 3y ago[deleted]
- nritchie 3y agoOr unitful.jl in Julia which evaluates the units at compile time resulting in no performance loss at runtime.
- sharkdp 3y agoF# is the only language I looked at that has a really powerful unit system. The author of that unit system wrote his PhD thesis on the subject [1]. Numbat's type system is actually pretty close to what was suggested in that thesis (in contrast to F#'s system, which is based on units — not dimensions). [1] https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-391.pdf https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-391.pdf
- runamuck 3y agoSo if I try to get the Falcon to do the Kessel run in two Parsecs, Numbat will raise an exception.
- pif 3y agoYou don't need a new programming language for something that C++ templates with integer constants give you for free.
- antoineMoPa 3y agoCan you provide examples?
- pif 3y ago- you define a template class accepting 1 constant integer for each dimension you want to consider (length and/or time and/or mass and/or temperature); - you define addition and subtraction between objects of one type returning an object of the same type; - you define multiplication and division as returning an object of a type with the dimensions summed or subtracted; - and you get dimensional correctness via type safety.
- n_plus_1_acc 3y agohttps://crates.io/crates/uom https://crates.io/crates/uom trivially convertable to cpp
- n_plus_1_acc 3y agohttps://www.boost.org/doc/libs/1_82_0/doc/html/boost_units/Units.html https://www.boost.org/doc/libs/1_82_0/doc/html/boost_units/U...
- leakim 3y agoIn Scala https://github.com/typelevel/squants https://github.com/typelevel/squants
- deleted 3y ago[deleted]
- vlovich123 3y agoSome of us don’t want to wait until the heat death of the universe for the code to compile (not a snipe at boost as a whole - boost units is quite bad iirc). There’s also performance problems if the compiler isn’t able to see through all the templates although that’s true for many things in this space. Finally iirc it doesn’t let you define your own custom units which is a common challenge with dimensional analysis as a library. If rust ever gets more complete const generics, then things like tiny-uom might work.
- enbugger 3y agoIn theory it can help to compute how many ore belts I need for producing full belt of white sciences in Factorio?
- jskherman 3y agoHow does Numbat infer the type/unit for operations that involve transcendental functions like the trigonometric functions and the natural logarithm? How about for exponents that are not integers (rational or irrational)? I've seen from to time some empirical equations that result to this. Usually, it's just hand-waved away and the non-integer units are ignored or dropped when the transcendental function is evaluated. I guess the trivial answer is probably add an extra factor with a value of 1 with the reciprocal units to result to the said type 1 for dimensionless units?
- iNic 3y agoThose types of functions are only allowed to take in dimensionless (ie scalar) values. Numbat seems to handle this correctly, see [1]. [1]: https://numbat.dev https://numbat.dev
- jskherman 3y agoI guess that's logical, still a bit tedious in converting values to scalars...
- geysersam 3y agoIf the value passed to the function isn't dimensionless there's very likely a unit error somewhere. I can't come up with an example where that would be a reasonable thing to do, but haven't thought too much about it.
- xigoi 3y agoIf you find yourself wanting to do that, you're probably making the exact kind of error that the language is meant to prevent.
- marginalia_nu 3y agoTo be fair, thse functions aren't defined for physical quantities. As a physicist, if you ever see units on the parameter to a trigonmetric function, you can be fairly certain something is wrong. You can derive this from how e.g. cos(x) can be written as a polynomial series, something like 1 - x^2 + whatever; and since 1 and x^2 would have different units if x is anything but unitless, you've goofed. That's a big reason why units are used in calculations in the first place. They basically act as a sort of checksum for your calculations.
- wwalexander 3y agoA month cannot be unambiguously represented as a length of time, as the length of a month is variable.
- michaelcampbell 3y agoIt looks as if they're defining a month as some amount of days. (30.4369, given the following.) >>> 1 day + 1 month 1 day + 1 month = 31.4369 day
- aimor 3y ago>>> 1 month -> seconds = 2_629_746 s [Time] Just playing around with this and really enjoying it.
- manifoldgeo 3y agoHow does something like `let y: Time = 1 year` work? Does it take into consideration the idea of leap years and leap seconds, counting a single year as 365.2422 days[0]? Or does it count as 365 days? I got curious and installed the CLI tool[1] and found that it does indeed account for leap second / leap years: >>> let jahr: Time = 1 year >>> let tage: Time = jahr -> days >>> tage = 365.243 day [Time] References: 0: https://museum.seiko.co.jp/en/knowledge/story_01/ https://museum.seiko.co.jp/en/knowledge/story_01/ 1: https://numbat.dev/doc/cli-installation.html https://numbat.dev/doc/cli-installation.html
- vlovich123 3y agoI feel like that’s unit confusion. Converting from year to day should require you to specify what calendar year you’re in to resolve the ambiguity. Otherwise I set an alarm for today + 1 year and things are off by 6 hours. Time is nasty because there’s lots of overloaded concepts and bugs hide in the implicit conversions between meanings. I’m also kinda curious what the underlying type is. Is it a double or do they use arbitrary precision math and take the perf hit.
- SenAnder 3y ago> I feel like that’s unit confusion. Converting from year to day should require you to specify what calendar year you’re in to resolve the ambiguity. A year has two meanings - a calendar year, with all the leap days and seconds and timezones, or a duration of time. The latter is still useful, e.g. when someone states that Proxima Centauri is 4.2 light-years away, they don't want to deal with leap-days. Decent time libraries have separate ways to deal with durations and dates.
- thriftwy 3y agoExcept there is also https://en.m.wikipedia.org/wiki/Sidereal_year https://en.m.wikipedia.org/wiki/Sidereal_year So I would say they need explicit different years.
- 3y ago
- V1ndaar 3y agoOr you could just use Nim [0], where this sort of thing can be implemented in Nim's macro system. Then you have a regular programming language combined with CT safe units. :) It even pretty much looks identical to those Numbat snippets! import unchained let earth_mass = 5.972168e24.kg let solar_mass = 1.9885e30.kg let lunar_mass = 7.342e22.kg let distance_sun = 1.AU # astronomical unit let distance_moon = 384_400.km let force_sun = G_Newton * earth_mass * solar_mass / distance_sun let force_moon = G_Newton * earth_mass * lunar_mass / distance_moon echo force_sun / force_moon # 69593.6 UnitLess Sorry for the shameless plug. ;) Numbat looks quite cool though and the article talks about a lot of things to think about when writing such a program / lib / programming language. [0]: https://github.com/SciNim/Unchained https://github.com/SciNim/Unchained
- deleted 3y ago[deleted]
- kragen 3y ago'can be implemented' is different from 'has been implemented' how does unchained handle gaussian elimination
- V1ndaar 3y agoGaussian elimination in what context even? If your LA library supports generic types, it might work. But generally generic math operations are tricky to get right, because math often does things that from a pure physical perspective don't make a whole lot of sense / you run into trouble with too many competing types due to temporary multiplication / divisions etc (which is a big issue in any statically typed language, because your container (vector, matrix, tensor whatever) type is typically a single unit type!
- kragen 3y agomost linear algebra requires vectors of multiple unit types. think of runge-kutta for a second-order system, for example, or just about any multivariate system. see https://yosefk.com/blog/can-your-static-type-system-handle-linear-algebra.html https://yosefk.com/blog/can-your-static-type-system-handle-l... for more information if your static type system can't handle that, it can't handle unit types for basic linear algebra subroutines
- indentit 3y agoCan it be used as a date calculator? I didn't see a way to specify "today" or "tomorrow". Like "today" + 14 days etc.
- BasilPH 3y agoI was also looking into this, and couldn't find a way to do it. My guess is that it has support for time, but not for calendars. The fact that a "month" is a static length points in this direction. Maybe there's going to be a calendar module in the future though?
- JNRowe 3y agoIf you're looking for a general solution to that specific type of problem, then dateutils¹ is really useful. It deals with conversions, durations, matching, repeats, etc. It also has a clear and well defined date input format, and being a collection of command line tools it is easy to mangle it in to other tools. ¹ http://www.fresse.org/dateutils http://www.fresse.org/dateutils
- indentit 3y agothanks for the recommendation, I hadn't come across this before and it looks really useful!
- cosmojg 3y agoSuper cool! I love when programming languages try to do more with types. Julia has a neat little library called Unitful.jl[1] which does almost exactly what Numbat does by taking advantage of Julia's extremely flexible type system. Extending it to cover all of Numbat's functionality could be trivially accomplished in a few lines. In fact, fun type magic like this is pretty much my primary motivation for using Julia in the first place. Not that I want to detract from the author's hard work, of course, I'm just very excited about Julia! Numbat is obviously an awesome project, and I can't wait to see where it leads! [1] https://painterqubits.github.io/Unitful.jl/stable/ https://painterqubits.github.io/Unitful.jl/stable/
- deleted 3y ago[deleted]
- sharkdp 3y agoI looked at Julia and Unitful.jl quite a bit when designing Numbat. It looks great. > Extending it to cover all of Numbat's functionality could be trivially accomplished in a few lines. Look, I'm not claiming that Numbat is superior. But I think Numbat might have its own little niche. And even if not, it's always good to have alternative solutions available. - Numbat is specifically designed to handle physical dimensions and units. It has a special syntax to give developers the best experience when dealing with units. You can just type "KiB" and have it be parsed as kibibytes. You can use the "->" operator to convert to other units. You can directly annotate functions with physical dimensions ("fn kinetic_energy(m: Mass, v: Velocity) -> Energy = …"). Other languages and their unit libraries might have the same functionality, but it has always been added as an afterthought. - Numbat has a static type system, Julia's is dynamic. - Numbat can be compiled to Web Assembly and you can run it in your browser. I'm not sure if that is possible with Julia? - Numbat might eventually be able to infer (physical dimension) function parameter types with its Hindley-Milner-style type system [1]. The only language that I know of that can do this is F#. The author of F#'s unit system wrote his PhD thesis on the subject [2], and Numbat follows the original approach in the thesis quite closely. [1] https://github.com/sharkdp/numbat/issues/29 https://github.com/sharkdp/numbat/issues/29 [2] https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-391.pdf https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-391.pdf
- hsfzxjy 3y agoRemind me of GNU Units https://www.gnu.org/software/units/ https://www.gnu.org/software/units/
- deleted 3y ago[deleted]
- docandrew 3y agoAda’s type system also allows compile-time checking of units like physical dimensions: https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gnat_ugn_unw/Performing-Dimensionality-Analysis-in-GNAT.html https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gnat_ugn_unw/Perfor... https://blog.adacore.com/uploads/dc.pdf https://blog.adacore.com/uploads/dc.pdf
- deleted 3y ago[deleted]
- praveen9920 3y agoIt’s interesting that they support currency units. Wonder how the conversion works. Probably have to provide conversion factor as well?
- eminence32 3y agoIt'll fetch current conversation rates from the internet
- sharkdp 3y agoYes. We use up-to-date currency exchange rates from the European Central Bank [1]. https://github.com/sharkdp/numbat/blob/786512175b99c195a7d5beaeb8f2c0593dff36de/numbat-exchange-rates/src/lib.rs#L36 https://github.com/sharkdp/numbat/blob/786512175b99c195a7d5b...
- freistil 3y agoThat's one of these things where you can spend quite some effort to get that right but it's not going to be useful for anything deeper. That's like saying "here, we have implemented Newton's mechanics in fundamental types, now you can in theory simulate a body up from its atoms!" and while that would sound compelling if you don't know much about physics, it would quickly become useless once you know more about physics.
- joeatwork 3y agoIf I’m reading this correctly, the Frink language has similar features (and also seems darn useful!) https://frinklang.org/ https://frinklang.org/
- sharkdp 3y agoI looked at Frink quite a bit and I agree that it looks cool. But as far as I can tell, it does not have a static type system. At least it's not based on physical dimensions. And it is not open source.
- thesuperbigfrog 3y agoFrink (https://frinklang.org/ https://frinklang.org/) is an older language with similar design goals. Frink runs on the JVM and is also available on Android. I use it as a general purpose calculator on my smartphone. It's really nice that Numbat is written in Rust :) Will have to try it out.
- nerdponx 3y agoThere's also Insect for interactive use: https://insect.sh/ https://insect.sh/
- sharkdp 3y agoInsect is the predecessor project. Numbat is the replacement. It also has an interactive version at https://numbat.dev/ https://numbat.dev/
- deleted 3y ago[deleted]
- sharkdp 3y agoFrink is not open source, unfortunately.
- thesuperbigfrog 3y ago>> Frink is not open source, unfortunately. True: https://frinklang.org/faq.html#OpenSource https://frinklang.org/faq.html#OpenSource Thanks for sharing Numbat with us. It looks great!
- exp1orer 3y agoThis is really cool! If the author is around, I notice in the README you mention the GNU units program, which I use quite a bit. I'm curious if you've made any notable divergences from it?
- sharkdp 3y agoThank you. I don't think we diverge from units on purpose anywhere, but I am probably not very familiar with its syntax, to be honest. I did however look at its huge collection of units and checked if there were any important units missing. I think we have a pretty comprehensive list of units that are supported by now in Numbat [1]. [1] https://numbat.dev/doc/list-units.html https://numbat.dev/doc/list-units.html
- kragen 3y agothe classic problem for such number systems is linear algebra https://yosefk.com/blog/can-your-static-type-system-handle-linear-algebra.html https://yosefk.com/blog/can-your-static-type-system-handle-l... the issue is that each column and each row of a matrix can have different units. worse, gauss-jordan elimination chooses which rows to operate on dynamically. there is eventually a solution to this problem in c++ far down the comments thread i don't see anything in https://numbat.dev/doc/type-system.html https://numbat.dev/doc/type-system.html about aggregate types such as vectors, matrices, maps, arrays, lists, trees, records, etc., though it does have a suggestively named scalar type. i wonder how it handles this sort of thing
- sharkdp 3y agoNo, we do not have aggregate types in Numbat yet. But it is definitely something I would like to support. Note that it is possible to construct a type system solution to this problem (vectors/matrices with non-uniform units). A colleague of mine has an excellent talk on this: https://www.youtube.com/watch?v=SLSTS-EvOx4 https://www.youtube.com/watch?v=SLSTS-EvOx4 By 'Scalar', in the document you referenced, we mean a dimensionless quantity. Not a scalar in the scalar-vector-matrix-tensor sense. Maybe I should rethink that notation.
- kragen 3y agothanks, i'll take a look i know it's possible (even in c++ apparently) but so far it seems difficult
- spott 3y agoInteresting article... though to be honest, I'm not sure I buy the premise. In the article, he states: "Let's call the matrix of all (xi 1) `X` and let's call the vector of all yi `Y`", and then states that the units of `X` are (m 1). But if you instead say the units of `X` are just m, the "1" is in units "m", then the problem goes away, the whole matrix has the same units ("m"), and everything works fine. I'll be honest in that I've never thought of a matrix having multiple units per column... and I can't think of any example where you aren't just putting the units in the wrong place. Let me know if you have a concrete example that might work.
- youssefabdelm 3y ago> On the other hand, 3 months + 2 lightyears is ill-typed, because the right-hand side is of type Length. You can change ‘years’ to ‘lightyears’ in the example above to see the resulting compiler error. Why not both? Make lightyears both Length and Time
- deleted 3y ago[deleted]
- mlhpdx 3y agoModeling compile-time units was one of the memes of c++ 11. One of many examples: https://benjaminjurke.com/content/articles/2015/compile-time-numerical-unit-dimension-checking/ https://benjaminjurke.com/content/articles/2015/compile-time...
- nutate 3y agoFirst project I've ever seen that made me instantly sponsor it. Then to only find out you wrote fd and hexyl and some other classics. Great work.
- merelysounds 3y agoImpressive! One thing I find unintuitive is the implementation of variable length units (like months or years) as an averaged constant. Then again, perhaps that’s the point - and e.g. working with months without specifying a calendar is just unintuitive.
- ttkciar 3y agoAfter having worked on accounting software for a living, which did need to precisely take into account the variable nature of time measurements, I greatly appreciate that Numbat has decided not to open that can of worms. Using averaged constants like this isn't applicable to all use-cases, but has the virtues of being simple and easy to reason about. IMO they did exactly the right thing by not trying to shoehorn an endless supply of complexity and pain into their language's type system. Users who do need to deal with date math can use a library.
- benhurmarcel 3y agoApparently this replaces https://github.com/sharkdp/insect https://github.com/sharkdp/insect
- sharkdp 3y agoYes. If you want to know more, you can read about it here: https://github.com/sharkdp/numbat/blob/master/assets/reasons-for-rewriting-in-rust.md https://github.com/sharkdp/numbat/blob/master/assets/reasons...
- SuperNinKenDo 3y agoStill reading the article, and really intrigued by and love this idea. But can I just say that I find this intro extremely well written. I feel like the writer is reading my thought process almost. Wvery time I start to form questions about decisions made in the language, it seems to answer them one or two paragraphs later. I feel like this is incredibly rare and yet incredibly important in an intro piece. Nicely done on the author['s]/[s'] part.
- eviks 3y agoCool that you can use actual 1 × 2 multiplication sign or 4 ⋅ 8 instead of that kludge of an asterisk *