# Lesson XIII
The brush meets the ink. Holding opens the way; unknown remains open; running closes the stroke.
## Try
```prolog
% ?- E = kernel, infer(E, [dup, add], Scheme).
% Scheme = scheme([requires(numeric, A)], effect([A|S], [A|S])).
% ?- E = kernel, infer(E, [push(int(1)), dup, add], Scheme).
% Scheme = scheme([], effect(S, [int|S])).
% ?- E = kernel, infer(E, [push(bool(true)), dup, add], Scheme).
% ERROR: forth_error(constraint, unsatisfied, requires(numeric, bool)).
```
## Lesson
```prolog
apply(Env, Word, Stack0, Stack) :-
find(Env, Word, InPattern -- OutPattern, Constraints, Goal),
bind(InPattern, Stack0),
solve(Constraints, []),
call(Goal),
build(OutPattern, Stack).
infer(Env, Words, scheme(Constraints, effect(In, Out))) :-
infer(Env, Words, effect(In, Out), RawConstraints, []),
solve(RawConstraints, Constraints).
% `solve/2` performs one local reduction at a time.
%
% * `requires(numeric, A)` stays open when `A` is a variable.
% * `requires(numeric, int)` disappears because `int` is numeric.
% * `requires(numeric, bool)` throws because `bool` has no numeric
% support.
solve([], []).
solve([Constraint|Constraints0], Constraints) :-
reduce1(Constraint, More),
solve(Constraints0, Rest),
append(More, Rest, Constraints).
reduce1(requires(Name, Type), [requires(Name, Type)]) :-
var(Type),
supports(_, Name),
!.
reduce1(requires(Name, Type), []) :-
supports(Type, Name),
!.
reduce1(Constraint, _) :-
throw(error(forth_error(constraint, unsatisfied, Constraint), _)).
```