Libra is a dimensional analysis library based on shapeless, spire and singleton-ops. It contains out of the box support for SI units for all numeric types.

## To Use

Libra supports JDK 8, scala versions 2.11.12, 2.12.11 and 2.13.2. The supported Scala.js version is 0.6.32

Add this to your `build.sbt`:

``````libraryDependencies += "com.github.to-ithaca" %% "libra" % "0.6.0"
``````

For Scala.js, add this to your `build.sbt`:

``````libraryDependencies += "com.github.to-ithaca" %%% "libra" % "0.6.0"
``````

## TL;DR

Example usage:

``````import spire.implicits._
import libra._, libra.implicits._
(3.m + 2.m).show
(3.m * 2.m).show
(1.0.km.to[Metre] + 2.0.m + 3.0.mm.to[Metre]).show
(3.0.s.to[Millisecond] / 3.0.ms).show
3.m + 2.kg // This should fail
// error: These quantities can't be added!
// Most likely they have different dimensions.  If not, make sure that there's an implicit AdditiveSemigroup in scope.
// Left: libra.Quantity[Int,libra.Term[libra.Length,libra.Metre,libra.Fraction[Int(1),Int(1)]] :: shapeless.HNil]
// Right: libra.Quantity[Int,libra.Term[libra.Mass,libra.Kilogram,libra.Fraction[Int(1),Int(1)]] :: shapeless.HNil]
// 3.m + 2.kg // This should fail
// ^^^^^^^^^^
``````

## Why?

When we deal with numeric quantities, we often resort to `Int`, `Double` or `Float` types. These are incommunicative and error prone.

``````val distance = 3.0 // 3 m
// distance: Double = 3.0 // 3 m
val time = 2.0 // 2 s
// time: Double = 2.0 // 2 s
val speed = distance + time // Oh no!
// speed: Double = 5.0
``````

There’s a mistake in our formula, but we won’t know without a decent set of tests.

Libra provides a `Quantity` which wraps base numeric types. It supports compile time dimensional analysis.

``````import spire.implicits._
import libra._, libra.implicits._
val distance = 3.0.m
val time = 2.0.s
distance + time
(distance / time).show // Yay!
// error: These quantities can't be added!
// Most likely they have different dimensions.  If not, make sure that there's an implicit AdditiveSemigroup in scope.
// Left: libra.Quantity[Double,libra.Term[libra.Length,libra.Metre,libra.Fraction[Int(1),Int(1)]] :: shapeless.HNil]
// Right: libra.Quantity[Double,libra.Term[libra.Time,libra.Second,libra.Fraction[Int(1),Int(1)]] :: shapeless.HNil]
// distance + time
// ^^^^^^^^^^^^^^^
``````

## Credits

In its incubation, Libra made heavy use of Typelevel Scala. It still makes use of shapeless, spire and singleton-ops. It wouldn’t be possible without these projects, their authors and contributors, so if you like Libra, please check them out.

Libra also uses:

## Alternatives

If Libra isn’t quite your cup of tea, definitely take a look at Squants. It’s also a great library for dimensional analysis, with a slightly different scope.