# Lesson XII The brush may be steady, yet a fine stroke asks for ink that will not run. ## Try ```prolog % ?- E = kernel, infer(E, [dup, add], Scheme). % Scheme = scheme([requires(numeric, A)], effect([A|S], [A|S])). % ?- E = kernel, infer(E, [dup, eq], Scheme). % Scheme = scheme([requires(equatable, B)], effect([B|T], [bool|T])). % ?- E = kernel, infer(E, [push(bool(true)), dup, add], Scheme). % Scheme = scheme([requires(numeric, bool)], effect(S, [bool|S])). ``` ## Lesson ```prolog word(kernel, add, [A::T, B::T|S] -- [C::T|S], [requires(numeric, T)], C is B + A). word(kernel, sub, [A::T, B::T|S] -- [C::T|S], [requires(numeric, T)], C is B - A). word(kernel, mul, [A::T, B::T|S] -- [C::T|S], [requires(numeric, T)], C is B * A). word(kernel, eq, [A::T, B::T|S] -- [Bool::bool|S], [requires(equatable, T)], (A == B -> Bool = true ; Bool = false)). word(kernel, lt, [A::T, B::T|S] -- [Bool::bool|S], [requires(numeric, T)], (B < A -> Bool = true ; Bool = false)). word(kernel, gt, [A::T, B::T|S] -- [Bool::bool|S], [requires(numeric, T)], (B > A -> Bool = true ; Bool = false)). find(Env0, Word, InOut, Constraints, Goal) :- nonvar(Env0), word(Env0, Word, StoredInOut, StoredConstraints, StoredGoal), copy_term(word(Word, StoredInOut, StoredConstraints, StoredGoal), word(Word, InOut, Constraints, Goal)). % Fixed words project through primitive rows. apply(Env, Word, Stack0, Stack) :- find(Env, Word, InPattern -- OutPattern, Constraints, Goal), bind(InPattern, Stack0), holds(Constraints), call(Goal), build(OutPattern, Stack). infer(Env, Words, scheme(Constraints, effect(In, Out))) :- infer(Env, Words, effect(In, Out), Constraints, []). infer(_, [], effect(Stack, Stack), Constraints, Constraints). infer(Env, [Word|Words], effect(Stack0, Stack), Constraints0, Constraints) :- infer1(Env, Word, effect(Stack0, Stack1), Constraints0, Constraints1), infer(Env, Words, effect(Stack1, Stack), Constraints1, Constraints). infer1(Env, push(Value), effect(Stack, [Type|Stack]), Constraints, Constraints) :- !, lit(Env, Value, Type). infer1(_Env, call, effect([quote(Scheme)|Stack0], Stack), Constraints0, Constraints) :- !, copy_term(Scheme, scheme(NewConstraints, effect(Stack0, Stack))), append(NewConstraints, Constraints, Constraints0). infer1(Env, Word, effect(Stack0, Stack), Constraints0, Constraints) :- find(Env, Word, InPattern -- OutPattern, NewConstraints, _Goal), types(InPattern, Stack0), types(OutPattern, Stack), append(NewConstraints, Constraints, Constraints0). supports(int, numeric). supports(int, equatable). supports(bool, equatable). holds([]). holds([requires(Name, Type)|Constraints]) :- nonvar(Type), supports(Type, Name), holds(Constraints). ```