# Lesson III
First see the gesture; then make it. A hand that cannot see before moving writes blindly.
## Try
```prolog
% ?- sig(over, In, Out).
% In = [_A, _B|_S],
% Out = [_B, _A, _B|_S].
% ?- sig(Word, [A, B], [B, A]).
% Word = swap.
% ?- infer([dup, swap], In, Out).
% In = [_A|_S],
% Out = [_A, _A|_S].
% ?- infer([swap, over], [A, B], Out).
% Out = [A, B, A].
% ?- infer([swap, over], In, [A, B, A]).
% In = [A, B].
```
## Learn
```prolog
% The runtime relation `apply/3` transforms actual stack values.
% This stage adds the first static relation:
%
% sig(Word, InputShape, OutputShape).
%
% Read the modes broadly:
%
% sig(?Word, ?InputStack, ?OutputStack).
%
% The relation can describe a known word, or discover which word has
% a known stack shape.
%
% `sig/3` does not execute a word. It describes the stack shape a
% word requires and produces. For the initial stack shufflers, the
% static clauses look almost identical to the runtime clauses because
% the words only move positions.
%
% Static signatures describe stack shapes without running the program.
sig(dup, [A|S], [A, A|S]).
sig(drop, [_|S], S).
sig(swap, [A, B|S], [B, A|S]).
sig(over, [A, B|S], [B, A, B|S]).
% Program inference follows the same sequencing shape as runtime, but
% it reads `sig/3` instead of `apply/3`. Similar structure does not
% make the two relations aliases. Runtime transforms actual stack
% values; inference relates static stack shapes without running the
% program.
%
% Inference follows the same sequencing shape on static effects.
infer([], Stack, Stack).
infer([Word|Words], Stack0, Stack) :-
sig(Word, Stack0, Stack1),
infer(Words, Stack1, Stack).
```