As explained in section 7.2.2, the signature checking for a linkage requires that a provided signature exactly matches the corresponding import signature. At first glance, this requirement appears to be overly strict; it might seem that the provided signature need only satisfy the imported signature. The reason for requiring an exact match at linkages is that a compound-unit/sig expression is expanded into a compound-unit expression. Thus, the number and order of the variables used for linking must be fully known at compile-time.
The exact-match requirement does not pose any obstacle as long as a unit is linked into only one other unit. In this case, the signature specified with the unit's tag can be contrived to match the importing signature. However, a single unit may need to be linked into different units, each of which may use different importing signatures. In this case, the tag's signature must be ``bigger'' than both of the uses, and a restricting signature is explicitly provided at each linkage. The tag must satisfy every restricting signature (this is a syntactic check), and each restricting signature must exactly match the importing signature (this is a run-time check).
In the example from section 7.2.2, both calculus@ and gravity@ import numerical procedures, so both import the arithmetic^ signature. However, calculus@ does not actually need the power procedure to implement integrate; therefore, calculus@ could be as effectively implemented in the following way:
(define-signature simple-arithmetic^ (add subtract multiply divide)) (define calculus@ (unit/sig calculus^ (import simple-arithmetic^) ...))
Now, the old compound-unit/sig expression for model@ no longer works. Although the old expression is still syntactically correct, link-time signature checking will discover that calculus@ expects an import matching the signature simple-arithmetic^ but it was provided a linkage with the signature arithmetic^. On the other hand, changing the signature associated with ARITHMETIC to simple-arithmetic^ would cause a link-time error for the linkage to gravity@, since it imports the arithmetic^ signature.
The solution is to restrict the signature of ARITHMETIC in the linkage for CALCULUS:
(define model@ (compound-unit/sig (import) (link (ARITHMETIC : arithmetic^ (arithmetic@)) (CALCULUS : calculus^ (calculus@ (ARITHMETIC : simple-arithmetic^)))) (GRAPHICS : graphics^ (graphics@)) (GRAVITY : gravity^ (gravity@ ARITHMETIC CALCULUS GRAPHICS))) (export (var (GRAVITY go)))))
A syntactic check will ensure that arithmetic^ satisfies simple-arithmetic^ (i.e., arithmetic^ contains at least the variables of simple-arithmetic^). Now, all link-time signature checks will succeed, as well.