In 3D games programming we use structure type called "vector", like D3DXVECTOR3, but we can remember from school that there are two separate geometrical objects: point and vector. Although both contain just 3 real numbers, there actually is a difference between them. Point represents a position in the space of some coordinate system (it's absolute - we can imagine it as a dot), while vector represents a translation by some distance and direction (it's relative - we can image it as an arrow). If we had separate types for points and vectors, we should define their operators this way:
POINT + POINT doesn't exist POINT - POINT = VECTOR (difference between points) POINT + VECTOR = POINT (translated point) POINT - VECTOR = POINT (point translated by inverted vector) VECTOR + VECTOR = VECTOR (sum) VECTOR - VECTOR = VECTOR (difference) VECTOR * float = VECTOR (scaling length) VECTOR / float = VECTOR (scaling length)
In my opinion it's good to express this difference by naming variables "position" (when we mean absolute position of an object) and "translation" (when we mean transformation of the object position), "size" (when we mean persisting size of the object) and "scale" (when we mean transforming object scale by some amount), "orientation" (when we mean how the object is currently rotated) and "rotation" (when we mean a transformation that is going to modify its orientation).
Although we never make such distinction by defining two separate data types for vectors or matrices, it happens sometimes in the analogical situation with date-time types. For example there is the DateTime structure in C# that represents an instant in time and the TimeSpan structure that represents a time interval.
Similar problem exists when we talk about any indices or pointers, especially if we want to use unsigned integers. Index or pointer cannot be negative and special "invalid" value can be defined as 0xffffffff as well as -1. I like to use unsigned type, e.g. because I can just check if (index < elemCount) instead of if (index >= 0 && index < elemCount). But what if we need a type to describe a relative offset? Obviously it should be signed because it can be negative. That's why C++ has types size_t (unsigned) and ptrdiff_t (signed). But things get complicated when we think about what type should the fseek function expect, as it can get either absolute (SEEK_SET) or relative position (SEEK_CUR, SEEK_END).
So all in all I think maybe we don't have to always define two separate types in our code, but we should always remember about this distinction when writing code.