5 ms·
Random question for the type experts out there: is there any language that lets me track the units of my numeric variables? For instance, something like this:
by pjungwir 12y ago
Random question for the type experts out there: is there any language that lets me track the units of my numeric variables? For instance, something like this:
float<km> drop(float<m> x0, float<s> duration) {
float<m> x = x0;
float<s> t = 0;
float<m/s> v = 0;
float<m/s^2> g = -10;
float<s> dt = 0.01;
while (t < duration) {
v += g*dt;
x += v*dt;
t += dt;
}
return x * (1<km>/1000<m>); // abbrev for a cast: (float<km/m>).001
}
Then I want the compiler to check that I'm not mixing up my units. It seems like this would be really useful, but I've never seen it before.
- sfk 12y agoFrom what I've read, Ada can do this.
- the_mitsuhiko 12y agoIn theory you can do that in any language that allows you to override operators. It's definitely being done in Rust. For instance you sleep for `Duration::milliseconds(10)`.
- bjz_ 12y agoStatically checked dimensional analysis is a great deal trickier though.
- thelinked 12y agoCheck out F#'s units of measure. http://msdn.microsoft.com/en-us/library/dd233243.aspx http://msdn.microsoft.com/en-us/library/dd233243.aspx
- hoggle 12y agoI've got to confess that I love how the design of MS languages regularly exposes my ignorance towards them. Edit: removed unrelated Wikipedia article (Unit Type)
- Dn_Ab 12y agopjungwir's example code is actually really close to what you'd see in F#. In F# you'd typically write it in a more functional way with say a recursive inner function but I'll leave it imperative for clarity's sake: [<Measure>] type s [<Measure>] type m [<Measure>] type km let mtokm (x:float<m>) = x * 1.<km>/1000.<m> //the types of g and ground are inferred let drop g ground (x0:float<m>) = let mutable x = x0 //type inferred here let mutable t = 0.0<s> let mutable v = 0.0<m/s> let dt = 0.01<s> while x >= ground do v <- v + g*dt x <- x + v*dt t <- t + dt t > drop -10.0<m/s^2> 0.<m> 50.<m> val it : float<s> = 3.16
- jeorgun 12y agoThe boost units library does this for C++.
- ers35 12y agoC++11 has user-defined literals: http://akrzemi1.wordpress.com/2012/08/12/user-defined-literals-part-i/ http://akrzemi1.wordpress.com/2012/08/12/user-defined-litera... http://en.wikipedia.org/wiki/C%2B%2B11#User-defined_literals http://en.wikipedia.org/wiki/C%2B%2B11#User-defined_literals
- karavelov 12y agoValue classes in Scala.
- dom96 12y agoNimrod features distinct types (http://build.nimrod-lang.org/docs/manual.html#distinct-type http://build.nimrod-lang.org/docs/manual.html#distinct-type) which allow you to implement something like this. Here is an example: https://github.com/def-/units/blob/master/units.nim#L220 https://github.com/def-/units/blob/master/units.nim#L220, I don't think it's complete yet though.
- stettix 12y agoScala has a number of libraries that lets you do this, for example Squants (http://www.squants.com/ http://www.squants.com/) and ScalaQuantity [https://github.com/zzorn/ScalaQuantity https://github.com/zzorn/ScalaQuantity].
- thiagof 12y agoSomething like this in Rust: https://blog.mozilla.org/research/2014/06/23/static-checking-of-units-in-servo/ https://blog.mozilla.org/research/2014/06/23/static-checking...
- tikhonj 12y agoHaskell has a few libraries to do this. I particularly like unittyped[1], which not only keeps track of units but also converts among compatible ones automatically. So 1 meter + 1 inch would typecheck and be converted automatically, but 1 meter + 1 second would give you a type error. The wiki page[2] has a bunch of examples, which I find pretty compelling. The one problem is that error messages are ugly, but they're ugly in a consistent way. You can just ignore the ugliness as unnecessary noise. *Main> (1 meter / second) * 5 second 5.0 m/s⋅s *Main> 2 meter + (1 meter / second) * 5 second 7.0 m One cute thing is that prefixes like "kilo" are just functions, letting you write things like: *Main> (42 kilo meter) `as` mile 26.097590073968025 mile *Main> gallon `as` (cubic (deci meter)) 4.546089999999999 dm⋅dm⋅dm⋅# Haskell is really good at dealing with numeric types in general. For example, it's quite easy for a library to define its own types, which then behave just like built-in ones including nice syntax. Unittyped follows this philosophy, letting you use units with things that aren't floats, like rational numbers, meaning you don't have to lose precision. *Main> (1 % 2) . meter `as` foot 625 % 381 ft It's a really slick design and manages to give you safety as well as additional expressivity (since units get converted automatically). [1]: https://hackage.haskell.org/package/unittyped https://hackage.haskell.org/package/unittyped
- berdario 12y agoI'm not sure why, but your examples aren't working with me... 1 *| meter |+| 35 *| centi meter 1.35 m works, but 1 meter fails with <interactive>:42:1: No instance for (Num (Value LengthDimension (U Meter) f0 -> t0)) arising from the literal `1' Possible fix: add an instance declaration for (Num (Value LengthDimension (U Meter) f0 -> t0)) In the expression: 1 In the expression: 1 meter In an equation for `it': it = 1 meter <interactive>:42:3: No instance for (Fractional f0) arising from a use of `meter' The type variable `f0' is ambiguous Possible fix: add a type signature that fixes these type variable(s) Note: there are several potential instances: instance Fractional Double -- Defined in `GHC.Float' instance Fractional Float -- Defined in `GHC.Float' instance Integral a => Fractional (GHC.Real.Ratio a) -- Defined in `GHC.Real' ...plus four others In the first argument of `1', namely `meter' In the expression: 1 meter In an equation for `it': it = 1 meter
- antrix 12y agoJava's pluggable type system can do this. The Checker framework provides a Units checker that can be plugged into the compile stage. See this blog for more info: http://blog.paralleluniverse.co/2014/05/01/modern-java/ http://blog.paralleluniverse.co/2014/05/01/modern-java/
- com2kid 12y agoAda also allows this. Has for quite some time, and it comes with a built in real world units system.
- ufo 12y agoFrink is a programming language that is all about keeping track of units: http://www.futureboy.us/frinkdocs/ http://www.futureboy.us/frinkdocs/
- joneil 12y agoAdding to all the other answers, here is what Haxe can do: class Metric { static function main() { var coinRadius:Millimeters = 12; var myHeight:Centimeters = 180; var raceLength:Meters = 200; var commuteDistance:Kilometers = 23; diff( coinRadius, myHeight ); // 1.788 meters diff( raceLength, commuteDistance ); // 22800 meters sum( commuteDistance, coinRadius ); // 23000.012 meters } static function diff( a:Meters, b:Meters ) { var d = Math.abs( a-b ); trace( '$d meters' ); } static function sum( a:Meters, b:Meters ) { var s = Math.abs( a+b ); trace( '$s meters' ); } } And the best part is, at runtime those are all floats. Take a look at the compiled JS code: (function () { "use strict"; var Metric = function() { }; Metric.main = function() { var coinRadius = 12; var myHeight = 180; var raceLength = 200; var commuteDistance = 23; Metric.diff(coinRadius / 1000,myHeight / 100); Metric.diff(raceLength,commuteDistance * 1000); Metric.sum(commuteDistance * 1000,coinRadius / 1000); }; Metric.diff = function(a,b) { var d = Math.abs(a - b); console.log("" + d + " meters"); }; Metric.sum = function(a,b) { var s = Math.abs(a + b); console.log("" + s + " meters"); }; Metric.main(); })(); The compiler takes care of all the conversions for you. To see the complete compileable example, including my type definitions for each unit, take a look at this gist: https://gist.github.com/jasononeil/b6b1845824f45f5d19df https://gist.github.com/jasononeil/b6b1845824f45f5d19df And the manual on abstract types: http://haxe.org/manual/abstracts http://haxe.org/manual/abstracts
- emmanueloga_ 12y agoJav^H^H^H errr... I mean, Xtend [1] :). It does this through a mechanism called "extension methods" [2]. Kotlin has something similar called "extension functions", so I'm guessing it should be possible with it too. 1: https://github.com/eclipse/xtext/blob/master/examples/org.eclipse.xtend.examples-container/contents/xtend-examples/src/example5/Units.xtend https://github.com/eclipse/xtext/blob/master/examples/org.ec... 2: http://www.eclipse.org/xtend/documentation.html#extensionMethods http://www.eclipse.org/xtend/documentation.html#extensionMet... 3: http://confluence.jetbrains.com/display/Kotlin/Extension+functions http://confluence.jetbrains.com/display/Kotlin/Extension+fun...