# Lesson XVII
A divided future is still a clear teaching. Keep it divided. The hand that cannot bear uncertainty loses the faces it was given.
## Try
```prolog
?- join1(int, bool, Joined).
Joined = union([int, bool]).
?- join([int, int], [bool, int], Joined).
Joined = [union([int, bool]), int].
?- E = kernel,
infer(E,
[push(int(2)), dup, push(int(1)), gt,
push(quote([drop, push(int(1))])),
push(quote([drop, push(bool(true))])),
ifte],
Scheme).
Scheme = scheme([], effect(S, [union([int, bool])|S])).
```
## Lesson
For shallow structural unions the join rules are intentionally small:
* identical types join to themselves;
* two different concrete types join to `union([...])`;
* stacks join pointwise.
This structural type data is simple, not a full set-theoretic type language.
```prolog
infer1(_Env, ifte, effect([quote(ElseScheme), quote(ThenScheme), bool|Input], Out), Constraints0, Constraints) :-
!,
copy_term(ThenScheme, scheme(ThenConstraints, effect(Input, ThenOut))),
append(ThenConstraints, Constraints1, Constraints0),
copy_term(ElseScheme, scheme(ElseConstraints, effect(Input, ElseOut))),
append(ElseConstraints, Constraints, Constraints1),
join(ThenOut, ElseOut, Out).
join([], [], []).
join([A|As], [B|Bs], [J|Js]) :-
join1(A, B, J),
join(As, Bs, Js).
join1(A, B, A) :- A == B, !.
join1(A, B, J) :-
( var(A) ; var(B) ),
!,
A = B,
J = A.
join1(A, B, union([A, B])).
```
[[16_lesson|Prev]] | [[18_lesson|Next]]