# Putting the Physics Into Measurements and Units

1. Aug 2, 2016
Updated the code for the most recent Swift changes in Xcode 8.

Other articles in this series:

1. (2) Multiplication and Division

Thanks to Chris Eidhof and Florian Kugler for helping me figure this out.

I ended the previous article with the plan to find a generic, declarative solution for expressing dependencies between physical quantities, such as velocity = length / time. Let’s continue that train of thought.

# A common form for equations

At the moment, the different `Unit…` classes don’t know anything about each other. As far as the type system is concerned, they are independent entities.1 In reality, though, quantities are connected to each other, and we express these relations in equations. We have already seen one example above, here are some more:

Dependencies between physical quantities
velocity = length / time
acceleration = velocity / time
area = length × length
volume = length × length × length = area × length
resistance = voltage / current
energy = power × time
density = mass / volume
force = mass × acceleration
pressure = force / area
torque = force × length

The first thing to note is that we can reduce all these equations to the same form: a = b × c. Division can be rewritten as multiplication: velocity = length / time ⇔ length = velocity × time. And although some equations have more than two factors, we can always introduce intermediary quantities to reduce them to two (see the volume equation above for an example).

# The `UnitProduct` protocol

So we need a way to express the relation a = b × c in the type system for a specific group of three unit classes, and we want to do this in a manner that can be adopted by any number of types. We can do this by defining a protocol named `UnitProduct` that has two associated types, `Factor1` and `Factor2`. We constrain these types to `Dimension`, the superclass of all dimensional units:

``````/// Describes the relation Self = Factor1 * Factor2.
protocol UnitProduct {
associatedtype Factor1: Dimension
associatedtype Factor2: Dimension
}
``````

What else do we need? In order to perform calculations, we need to specify the actual units the values should be converted to for the calculation. In other words, we must tell the type system that meters divided by seconds yields a result in meters per second and not, for instance, kilometers per hour. Let’s add a static method called `defaultUnitMapping()` to the protocol for that purpose. It returns a three-tuple of matching units, one each for a, b, and c.

Ideally, I’d like the type of this return value to be `(Factor1, Factor2, Self)`, but the `Self` will later cause problems when we implement the protocol for a concrete type, such as `UnitLength`. The `Unit…` types are non-final classes, meaning they can be subclassed. Now if `UnitLength` adopted the protocol and implemented this method by returning a `UnitLength` instance for `Self`, any subclass would inherit the conformance, but no longer fulfill the protocol contract because `Self` now refers to the subclass’s type. The compiler doesn’t allow such an implementation for that reason. This would be different if `UnitLength` were a value type or a final class.

As a workaround, we can introduce a third associated type to represent the product of the multiplication. I don’t like this solution because it forces adopters of the protocol to specify themselves as an associated type, which is really unintuitive. But it works. The complete protocol becomes:

``````protocol UnitProduct {
associatedtype Factor1: Dimension
associatedtype Factor2: Dimension
associatedtype Product: Dimension // is always == Self

static func defaultUnitMapping() -> (Factor1, Factor2, Product)
}
``````

This is enough to express the mathematical relation in the type system and provides sufficient information about the unit relationships to perform calculations.

Next, let’s write a concrete implementation. Remember, we want to model the relation `UnitLength` = `UnitSpeed` × `UnitDuration`, so we want `UnitLength` to adopt the protocol:

``````/// UnitLength = UnitSpeed * UnitDuration
/// ⇔ UnitSpeed = UnitLength / UnitDuration
extension UnitLength: UnitProduct {
typealias Factor1 = UnitSpeed
typealias Factor2 = UnitDuration
typealias Product = UnitLength

static func defaultUnitMapping() -> (UnitSpeed, UnitDuration, UnitLength) {
return (.metersPerSecond, .seconds, .meters)
}
}
``````

I have explicitly specified the associated types here with typealiases, but we could leave those out. The compiler can infer the types from the return type of the `defaultUnitMapping()` method. We return the triple `(.metersPerSecond, .seconds, .meters)`, specifying that these units are coherent (multiplying or dividing two yields the third). These units also happen to be their unit type’s respective base units, but that is not necessarily the case. We could have chosen other values, such as `(.kilometersPerHour, .hours, .kilometers)`, as long as they are coherent with each other.

There is one more step until we can perform a calculation. We need to implement the multiplication operator for our protocol. The function type says, “this is an implementation of the `*` operator for types adopting the `UnitProduct` protocol, where the left argument is a `Measurement<Factor1>`, the right argument is a `Measurement<Factor2>`, and the return value is a `Measurement<Product>`”:

``````/// UnitProduct.Product = Factor1 * Factor2
func * <UnitType: UnitProduct> (lhs: Measurement<UnitType.Factor1>, rhs: Measurement<UnitType.Factor2>)
-> Measurement<UnitType> where UnitType: Dimension, UnitType == UnitType.Product {
let (leftUnit, rightUnit, resultUnit) = UnitType.defaultUnitMapping()
let quantity = lhs.converted(to: leftUnit).value
* rhs.converted(to: rightUnit).value
return Measurement(value: quantity, unit: resultUnit)
}
``````

The function body has three steps. First we retrieve the unit mapping from the protocol. Then we convert the two arguments to their respective target units and multiply the amounts. Lastly, we wrap the result in a new `Measurement` value and return it. Let’s try it out:

``````let speed = Measurement(value: 20, unit: UnitSpeed.kilometersPerHour)
// → 20.0 km/h
let time = Measurement(value: 2, unit: UnitDuration.hours)
// → 2.0 hr
let distance: Measurement<UnitLength> = speed * time
// → 40000.032 m
``````

It works, awesome! Three observations:

1. The type checker currently cannot infer the return type of the multiplication automatically, we have to specify `Measurement<UnitLength>` explicitly. I’m not quite sure why that is. I experimented with various constraints for the generic parameters of the `*` function, but I couldn’t get it to work.

2. The result is in meters. Not a big deal, but it would be nicer if it were in kilometers, given that the arguments of the multiplication were in kilometers per hour and hours, respectively. More on that in the next article.

3. There is a small rounding error in the result, caused by a rounding error in the conversion from kilometers per hour to meters per second.

## a × b ⇔ b × a

We need to write three more functions to complete the task, two for division and another one for multiplication. Multiplication is commutative, so time * speed should work just like speed * time. This is not true yet for our solution, but it is easy to add. Simply add another overload for `*`, swapping the two arguments. The function simply forwards to the first one:

``````/// UnitProduct.Product = Factor2 * Factor1
func * <UnitType: UnitProduct>(lhs: Measurement<UnitType.Factor2>, rhs: Measurement<UnitType.Factor1>)
-> Measurement<UnitType> where UnitType: Dimension, UnitType == UnitType.Product {
return rhs * lhs
}

let distance2: Measurement<UnitLength> = time * speed
// → 40000.032 m
``````

# Division

Similarly, for division we need one overload for `Product` / `Factor1` and one for `Product` / `Factor2`:

``````/// UnitProduct / Factor1 = Factor2
func / <UnitType: UnitProduct>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType.Factor1>)
-> Measurement<UnitType.Factor2> where UnitType: Dimension, UnitType == UnitType.Product {
let (rightUnit, resultUnit, leftUnit) = UnitType.defaultUnitMapping()
let quantity = lhs.converted(to: leftUnit).value / rhs.converted(to: rightUnit).value
return Measurement(value: quantity, unit: resultUnit)
}

/// UnitProduct / Factor2 = Factor1
func / <UnitType: UnitProduct>(lhs: Measurement<UnitType>, rhs: Measurement<UnitType.Factor2>)
-> Measurement<UnitType.Factor1> where UnitType: Dimension, UnitType == UnitType.Product {
let (resultUnit, rightUnit, leftUnit) = UnitType.defaultUnitMapping()
let quantity = lhs.converted(to: leftUnit).value / rhs.converted(to: rightUnit).value
return Measurement(value: quantity, unit: resultUnit)
}

let timeReversed = distance / speed
// → 7200.0 s
timeReversed.converted(to: .hours)
// → 2.0 hr
let speedReversed = distance / time
// → 5.55556 m/s
speedReversed.converted(to: .kilometersPerHour)
// → 20.0 km/h
``````

Interestingly, the type inference works for the division operations. I suspect it has something to do with the fact that in the division functions one of the arguments can be directly traced back to the generic parameter `UnitType`, whereas the arguments of the multiplication functions are only associated types of the generic parameter. I tried to introduce `Factor1` and `Factor2` as full-fledged generic parameters to the multiplication functions, but it didn’t change anything, though. Please let me know if you can explain this.

# Adopt the protocol with five lines of code

That’s it. Now, all we need to do to express the dependencies between three physical quantities is adopt the protocol and implement a single one-line function. Here it is for resistance (`UnitElectricResistance`), voltage (`UnitElectricPotentialDifference`), and current (`UnitElectricCurrent`):

``````/// UnitElectricPotentialDifference = UnitElectricResistance * UnitElectricCurrent
extension UnitElectricPotentialDifference: UnitProduct {
static func defaultUnitMapping() -> (UnitElectricResistance, UnitElectricCurrent, UnitElectricPotentialDifference) {
return (.ohms, .amperes, .volts)
}
}
``````

And in use:

``````let voltage = Measurement(value: 5, unit: UnitElectricPotentialDifference.volts)
// → 5.0 V
let current = Measurement(value: 500, unit: UnitElectricCurrent.milliamperes)
// → 500.0 mA
let resistance = voltage / current
// → 10.0 Ω
``````

# Conclusion

I think this is pretty cool, and it shows how a powerful type system can help us write correct code. Once the relations are defined, the compiler will not allow calculations with types that don’t make sense (e.g. mixing up numerator and denominator). And when type inference works, the compiler can even tell you the result type of an operation (note that in the last example above we have not specified the type of the `resistance` variable).

I also like that this is a declarative way of expressing these relationships. We essentially tell the compiler, “hey, this is how these three quantities are related, you figure out the rest”, and all the calculations and type checks just work.

# Outlook

In part 3, I would like to present a possible solution for preserving the units during a calculation (kilometers divided by hours should yield kilometers per hours, not meters per second), and discuss one more limitation that the current solution has. Stay tuned!

1. They have a common superclass, but that is not important at the moment. ↩︎