:- ensure_loaded(typeops).

:- import_pred(prolog_meta, '='/2).
:- import_type(prolog_num).

:- type list(T) --> [] ; [ T | list(T) ].
:- type element --> {X | atomic(X)}.

:- pred isa_list(list(T)). 
:- pred atomic(T).
:- pred !.
:- pred append(list(T), list(T), list(@T)).
:- pred flatten(list(top), list(T)).


append([], Ys, Ys).
append([X|Xs], Ys, [X|Zs]) :- append(Xs, Ys, Zs).

isa_list([]).

isa_list([_H|T]) :-
  isa_list(T).

flatten([], []).
flatten([X|Rest], FlatList) :-
  isa_list(X), !,
  flatten(X, FlatX),
  flatten(Rest, FlatRest),
  append(FlatX, FlatRest, FlatList).
flatten([X|Rest], [X|FlatRest]) :-
  % \+ isa_list(X), 
  atomic(X),                    % type-predicate
  flatten(Rest, FlatRest).


:- flatten(a,K).                % ill-typed
:- flatten(a,[a]).              % ill-typed
:- flatten([[1|2]], M).         % ok !!!  but fail
:- flatten([a,b,[c,[d],e]],M).  % ok

:- A = [1|2], flatten([A], L).  % ill-typed and fail





