Frink – Numbers with units of measure
Lars Fosdal - 21/Jul/2020
Lars Fosdal - 21/Jul/2020
[SHOWTOGROUPS=4,20,22]
As unusual programming languages go, this one actually is pretty amazing.
It adds units of measure to the number.
“One day Alan Eliasen read a fart joke and got so mad he invented a programming language. 20 years later Frink is one of the best special purpose languages for dealing with units.“But why do we need a language just for dealing with units?” Glad you asked! Intro to Units A unit is the physical property a number represents, like distance or time. We almost always are talking about SI units, or Système international.”
by Hillel Wayne
One day Alan Eliasen read a fart joke and got so mad he invented a programming language. 20 years later Frink is one of the best special purpose languages for dealing with units.
“But why do we need a language just for dealing with units?” Glad you asked!
Intro to Units
A unit is the physical property a number represents, like distance or time. We almost always are talking about Для просмотра ссылки Войдиили Зарегистрируйся, or Système international. That’s things like meters, seconds, kilograms, along with prefixes like kilo- and mega-. One kilometer = 1000 meters, 1 centimeter = 1/100th of a meter.
Units can have exponents: m² is square meters, m³ is cubic meters, m * s-1 is speed. These form new physical properties, or dimensions. We can multiply and divide numbers with different dimensions but not add them. I can add 1 m + 1 m, but not 1 m + 1 kg. A unit-aware language needs to be able to track units and make sure that I don’t add incompatible dimensions. It also should also make sure that I pass correct units into functions that depend on units. A pressure calculation would take an area and a force, not a frequency and an amperage.
Simple, right?
Nope
First of all, there are multiple different representations of units. There’s the SI system, which all sane, right-thinking nations use, and then there’s the American system.Для просмотра ссылки Войдиили Зарегистрируйся Feet and meters are both distance. Is it okay to mix feet and meters? This is the bug that destroyed the Для просмотра ссылки Войди или Зарегистрируйся. But there are also valid uses cases where you’d want to mix them! When I cook, I use a mix of metric weights and American volumes, like 1 cup of water and 128 grams of flour. In the UK, beer is measured Для просмотра ссылки Войди или Зарегистрируйся but its alcohol by volume is measured in SI.
Different dimensions doesn’t always mean the units are incompatible. There’s a nonstandard set of units called “Gaussian units” used in some niches of physics. In SI, capacitance is measured in Farads, which has dimensions A² s⁴ kg-1 m−2. In Gaussian units, capacitance is measured in cm. If you’re explicit about what you’re doing you can add these seemingly-incompatible dimensions.
Dimensions aren’t unique, and two incompatible physical quantities can have the same dimension. The canonical example is that energy and angular force are both measured in Newton-meters.Для просмотра ссылки Войдиили Зарегистрируйся There are also plenty of domain specific examples. As you enter a gravity well, the rate at which gravitational force changes has dimensions N/m. Surface tension is also measured in N/m.
What else?
или Зарегистрируйся.
Some solutions
Adding units of measure to a language is tricky. It’s not just that there are many hard domain problems, there’s also different tradeoffs in solutions. Do we want compile-time or runtime correctness? Should units be part of the type system or is there a better representation? How do we handle derived units? How do we handle generics? A good overview of the design challenges is Для просмотра ссылки Войдиили Зарегистрируйся, which discusses some of the solutions proposed for Ada.
Для просмотра ссылки Войдиили Зарегистрируйся covers how various languages approach measurements. For the most part, they punt the question to preprocessors and libraries, limiting how much they can help you. The only mainstream language with built-in support for units of measure is F#. F# focuses on catching all errors at compile time. All conversions between units must be made explicit, so you can’t accidentally add feet and meters. The price for this is flexibility: you can’t add centimeters and meters, either.
// Mass, grams.
[<Measure>] type g
// Mass, kilograms.
[<Measure>] type kg
// Define conversion constants.
let gramsPerKilogram : float<g kg^-1> = 1000.0<g/kg>
// Define conversion functions.
let convertGramsToKilograms (x : float<g>) = x / gramsPerKilogram
That’s a good design choice for F#’s goals. It adds boilerplate but keeps your software from going haywire. This is appropriate for industrial software where a lot of people could be affected by a bug.
It’s less appropriate for low-stakes, small scale work. Boilerplate makes it harder to use things interactively. If I’m trying to find the Titanic’s weight in cups of rice I don’t want to spend ten minutes writing unit conversions. For that, the most common tool is Для просмотра ссылки Войдиили Зарегистрируйся, a GNU program for conversions:
You have: 12 ft + 3 in + 3|8 in
You want: ft
* 12.28125
/ 0.081424936
units is a fine piece of software, but it’s not a programming language. I want a language that has built-in dimensional analysis but doesn’t need a lot of boilerplate. Something more powerful than units but not as strict as F#.
[/SHOWTOGROUPS]
As unusual programming languages go, this one actually is pretty amazing.
It adds units of measure to the number.
“One day Alan Eliasen read a fart joke and got so mad he invented a programming language. 20 years later Frink is one of the best special purpose languages for dealing with units.“But why do we need a language just for dealing with units?” Glad you asked! Intro to Units A unit is the physical property a number represents, like distance or time. We almost always are talking about SI units, or Système international.”
by Hillel Wayne
One day Alan Eliasen read a fart joke and got so mad he invented a programming language. 20 years later Frink is one of the best special purpose languages for dealing with units.
“But why do we need a language just for dealing with units?” Glad you asked!
Intro to Units
A unit is the physical property a number represents, like distance or time. We almost always are talking about Для просмотра ссылки Войди
Units can have exponents: m² is square meters, m³ is cubic meters, m * s-1 is speed. These form new physical properties, or dimensions. We can multiply and divide numbers with different dimensions but not add them. I can add 1 m + 1 m, but not 1 m + 1 kg. A unit-aware language needs to be able to track units and make sure that I don’t add incompatible dimensions. It also should also make sure that I pass correct units into functions that depend on units. A pressure calculation would take an area and a force, not a frequency and an amperage.
Simple, right?
Nope
First of all, there are multiple different representations of units. There’s the SI system, which all sane, right-thinking nations use, and then there’s the American system.Для просмотра ссылки Войди
Different dimensions doesn’t always mean the units are incompatible. There’s a nonstandard set of units called “Gaussian units” used in some niches of physics. In SI, capacitance is measured in Farads, which has dimensions A² s⁴ kg-1 m−2. In Gaussian units, capacitance is measured in cm. If you’re explicit about what you’re doing you can add these seemingly-incompatible dimensions.
Dimensions aren’t unique, and two incompatible physical quantities can have the same dimension. The canonical example is that energy and angular force are both measured in Newton-meters.Для просмотра ссылки Войди
What else?
- What’s 200° + 360°? It could be 200° or 560°, depending on we have a “circular angle” or a “rotational angle” (like driving a screw in).
- Some quantities are unitless. What’s 20° + 1 radian? They’re both unitless quantities that have compatible dimensions. What about adding two ratios? What about adding a radian to a ratio?
- Units can have additional limitations. You can subtract timestamps from each other but not add them.
- Units can have different historical values. A foot is defined as exactly 0.3048 meters. Before 1959, though, it was 0.3048006 meters. This is means that all historical documents have a different measurement of foot. And there was a period of time where we used Для просмотра ссылки Войди
или Зарегистрируйся definitions in different places! - Uncertainties. If you’re working with physical measurements, all of your measurements will have some amount of uncertainty. What happens when you add two meters, plus or minus a centimeter?
Some solutions
Adding units of measure to a language is tricky. It’s not just that there are many hard domain problems, there’s also different tradeoffs in solutions. Do we want compile-time or runtime correctness? Should units be part of the type system or is there a better representation? How do we handle derived units? How do we handle generics? A good overview of the design challenges is Для просмотра ссылки Войди
Для просмотра ссылки Войди
// Mass, grams.
[<Measure>] type g
// Mass, kilograms.
[<Measure>] type kg
// Define conversion constants.
let gramsPerKilogram : float<g kg^-1> = 1000.0<g/kg>
// Define conversion functions.
let convertGramsToKilograms (x : float<g>) = x / gramsPerKilogram
That’s a good design choice for F#’s goals. It adds boilerplate but keeps your software from going haywire. This is appropriate for industrial software where a lot of people could be affected by a bug.
It’s less appropriate for low-stakes, small scale work. Boilerplate makes it harder to use things interactively. If I’m trying to find the Titanic’s weight in cups of rice I don’t want to spend ten minutes writing unit conversions. For that, the most common tool is Для просмотра ссылки Войди
You have: 12 ft + 3 in + 3|8 in
You want: ft
* 12.28125
/ 0.081424936
units is a fine piece of software, but it’s not a programming language. I want a language that has built-in dimensional analysis but doesn’t need a lot of boilerplate. Something more powerful than units but not as strict as F#.
[/SHOWTOGROUPS]