Measure
skylark-measure is a library dealing with unit-of-measure definition, arithmetic, simplification and conversions in a type-safe manner.
Configuration
Simple usage
Many units of measure are defined for you.
Easily compose another unit of measure as stand-alone entities or in relation to an already-defined one.
Any unit of measure will have a set of basic properties that you would naturally expect to interrogate.
You can compose more complex ones by multiplying, dividing, and exponentiating.
You can find our the conversion factor from one to
another. No conversion factor may exist.
When dealing with marshalling/encoding/serialization, you can store units of measure along with a numeric value as a plain string.
With AnyMeasureParsers
you can turn that string back into a measure.
It's easy to compose numerical quantities with units of measure using a dot or postfix syntax or via full instantiation.
You can perform the expected arithmetic operations on quantities.
Quantity conversions are supported via the same to
operator. Basic converters are pre-defined. Conversions for product, ratio, and exponential measures
are defined by converters and require their own CanConvert
instances of their components' conversions.
Ambiguity in choosing the right conversion factor due to a substance or its properties (e.g. specific gravity) can be resolved by importing right implicits.
Typed Measure
vs. untyped AnyMeasure
skylark-measure gives you the freedom and flexibility to work with measures of a defined dimension (e.g. MassMeasure
) or AnyMeasure
- a measure whose dimension can only be known at run time.
The choice of which to work with depends on the individual API you would like to expose and enforce.
In the situation where you know you must receive a MassMeasure
, you would encode exactly as natural logic or physics would dictate. There is, hence, no chance
someone can pass a quantity in units of LuminousFluxMeasure
, for example, where a quantity in units of MassMeasure
is expected (unless one finds compiler errors
aesthetically pleasing).
In other situations, where knowledge of a measure's dimension is uncertain, one would rely on AnyMeasure
.
Operations on AnyMeasure
yields another AnyMeasure
and thus have less strict type requirements than a type derived from Measure
.
You can always match
on AnyMeasure
to check or assert a certain shape.
Overriding default behavior
The default arithmetic, conversion, and simplification operations are defined for both dimensional measure types and AnyMeasure
.
Arithmetic
skylark-measure relies on the presence of implicit
type classes CanMultiplyMeasure
, CanDivideMeasure
, and CanExponentiateMeasure
to perform arithmetic operations.
By default
m1 * m2
returnsProductMeasure(m1, m2)
;m1 / m2
returnsRatioMeasure(m1, m2)
;m ^ n
returnExponentialMeasure(m, n
).
One can, however, override the return type by proving a custom implicit class that derives from one of the three Can*Measure
traits.
For example, say when one does b / s
(bits per second), one wants to work with a custom BitRateMeasure
instead of the default RatioMeasure(bit, s)
.
One would then need to define the custom object like InformationTimeCanDivide
:
Conversion
skylark-measure relies on the presence of implicit
type class CanConvert
and helper Converter
type to convert between measures of different type.