There are a couple of ways of protecting units with contracts. One way is useful when writing new signatures, and the other handles the case when a unit must conform to an already existing signature.
When contracts are added to a signature, then all units which implement that signature are protected by those contracts. The following version of the toy-factory^ signature adds the contracts previously written in comments:
"contracted-toy-factory-sig.rkt"
Now we take the previous implementation of simple-factory@ and implement this version of toy-factory^ instead:
"contracted-simple-factory-unit.rkt"
(toy'blue)))(toycol)))
As before, we can invoke our new unit and bind the exports so that we can use them. This time, however, misusing the exports causes the appropriate contract errors.
Factory started.
> (build-toys3)(list (toy 'blue) (toy 'blue) (toy 'blue))
> (build-toys#f)build-toys: contract violation
expected: integer?
given: #f
in: the 1st argument of
(-> integer? (listof toy?))
contract from:
(unit contracted-simple-factory@)
blaming: top-level
(assuming the contract is correct)
at: <collects>/racket/private/unit/exptime/import-export.r
kt:494:23
> (repaint3'blue)repaint: contract violation
expected: toy?
given: 3
in: the 1st argument of
(-> toy? symbol? toy?)
contract from:
(unit contracted-simple-factory@)
blaming: top-level
(assuming the contract is correct)
at: <collects>/racket/private/unit/exptime/import-export.r
kt:494:23
However, sometimes we may have a unit that must conform to an already existing signature that is not contracted. In this case, we can create a unit contract with unit/c or use the define-unit/contract form, which defines a unit which has been wrapped with a unit contract.
For example, here’s a version of toy-factory@ which still implements the regular toy-factory^, but whose exports have been protected with an appropriate unit contract.
"wrapped-simple-factory-unit.rkt"
(toy'blue)))(toycol)))
Factory started.
toy?180: undefined;
cannot use before initialization
> (build-toys3)(list (toy 'blue) (toy 'blue) (toy 'blue))
> (build-toys#f)build-toys: contract violation
expected: integer?
given: #f
in: the 1st argument of
(-> integer? (listof toy?))
contract from:
(unit contracted-simple-factory@)
blaming: top-level
(assuming the contract is correct)
at: <collects>/racket/private/unit/exptime/import-export.r
kt:494:23
> (repaint3'blue)repaint: contract violation
expected: toy?
given: 3
in: the 1st argument of
(-> toy? symbol? toy?)
contract from:
(unit contracted-simple-factory@)
blaming: top-level
(assuming the contract is correct)
at: <collects>/racket/private/unit/exptime/import-export.r
kt:494:23