* Once one has optional type declarations, the need for type-specific
arithmetic primitives is reduced or eliminated.

How far down the call chain is the type inference to be done; in other
words, do these declarations only affect calls that are statically
within the lambda where they appear?

Since it *optional* static typing, I'm assuming that the specific
operations are "consistent" in the sense of the following example:
If (and (fixnum? x) (fixnum? y))
then: (eqv? (+ x y) (fx+ x y))
In that case the use of fx+ rather than + is basically compiler hint
that the operands are expected (required) to be fixnums. Then:
(fx+ x y)
is equivalent to:
(let ((x_f :: <fixnum>) (y_f :: <fixnum>))
(+ x_f y_f))
and the fx+ operation is unneeded: The same effect *and efficiency*
can be achieved with suitable type declarations and/or type inference.
Obviously one would have a cast operator as a shorthand. Kawa has:
(as <TYPE> <expr>)
which is equivalent to:
(let ((tmp :: <TYPE> <expr>)) tmp)
In Kawa <TYPE> is actually an identifier that evaluates to a Type value,
and (as ...) is a function that is specially optimized by the compiler.
However, I don't think R6RS should not go that far, but could just
define (as <TYPE> <expr>) as a special form.
To answer your actual (I think) question: Type declarations are local
and apply lexically, just as in C, Java - and Common Lisp.
Note we don't need (for this purpose, at least) a fancy type system
with higher-order types. Just simple types corresponding to the
various type predicates: E.g. corresponding to (procedure? x)
we'd have a plain <procedure> type specifier.
--
--Per Bothner
per@xxxxxxxxxxx http://per.bothner.com/