A derived type inherits operators and values type LENGTH is new FLOAT; -- two new types with type AREA is new FLOAT; -- same values and functions L1, L2, L3 : LENGTH; A1, A2, A3 : AREA; L1 := L2 + L3; -- so far so good A1 := A2 + A3; -- still OK A1 := A2 + L2; -- will get error, OK not same dimension L1 := L2 * L3; -- oopse! This should get error, but none A1 := L2 * L3; -- oopse! This gets error but is legal physics put(float(L1)); -- OK if Text_IO.Float_IO instantiated A "subtype" will not help. Think of a subtype as a synonymous name of another type. ( Who says a subtype needs constraints? ) type LENGTH is new FLOAT; subtype AREA is LENGTH; L1, L2, L3 : LENGTH; A1, A2, A3 : AREA; A1 := A2 + L2; -- no error, yet wrong physics L1 := L2 * L3; -- no error, yet wrong physics Also misleading for the reader/user would be: subtype LENGTH is FLOAT; subtype AREA is FLOAT; L1, L2, L3 : LENGTH; A1, A2, A3 : AREA; L1 := L2 * L3; -- would work, but it should not A1 := A2 + L3; -- would work, but it should not Put(L1); -- OK if Text_IO.Float_IO instantiated Private types come with substitution, equality and inequality type MINE is private; A, B : MINE; -- you can create objects of private types C : MINE := any_thing; -- Illegal ! no values for a private type A := B; -- OK If A = B then -- OK if A /= B then -- OK if A > B then -- NO! undefined, may not be a scalar A := A + B; -- NO! undefined .. also * / - ** etc. Put(A); -- NO! undefined, do your own Put