anchor.diff:  parse_constraints([ConstraintType | Rest], Substitutions) ->
       case ConstraintType of
           {type,_,constraint,[{atom,_,is_subtype},[{var,_,Variable},Type]]} ->
  -            NewSubstitutions = gb_trees:insert(Variable, Type, Substitutions),
  -            parse_constraints(Rest, NewSubstitutions);
  +            case gb_trees:lookup(Variable, Substitutions) of
  +                {value,Val} ->
  +                    case equal_types(Val, Type) of
  +                        true ->
  +                            NewSubstitutions = gb_trees:enter(Variable, Type, Substitutions),
  +                            parse_constraints(Rest, NewSubstitutions);
  +                        false ->
  +                            throw({parse_error, Val})
  +                    end;
  +                none ->
  +                    NewSubstitutions = gb_trees:insert(Variable, Type, Substitutions),
  +                    parse_constraints(Rest, NewSubstitutions)
  +            end;
           _ ->
               ct:pal("unknown constraint ~w", [ConstraintType]),
               parse_constraints(Rest, Substitutions)
  
positive.code:         none -> {var,_Line,VarName}
      end;
  
  substitute_constraints({type, Line,bounded_fun, [FunType, _Constraints]}, Substitutions) ->
      substitute_constraints(FunType, Substitutions);
  
  % generic types
  
negative.code:     ct:pal("~w", [Substitutions]),
      throw({subst_error, unknown_expression}),
      exit(foobar).
  
  % type equality minus line number
  equal_types(Left, Right)  when is_list(Left) andalso is_list(Right) ->
      lists:all(fun ({L, R}) ->
                        equal_types(L, R)
                end, lists:zip(Left, Right));
  equal_types({type,_, Type, LeftList}, {type,_, Type, RightList} ) ->
      equal_types(LeftList, RightList);
  equal_types(_, _) ->
      false.
  
  