:- ensure_loaded(typeops).

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

% :- typical_intern(assert(alltrace)).

:- type list(T) --> []; [T|list(T)].

:- type atom  --> {X | (atom(X)) }.

:- predl ttt(list(T)).



:- type element(T) --> {X | (integer(X), X > 0, T = posint) };
	               {X | (atom(X), T = atom) }.

% :- type list(posint) > element(posint).  % Alternative to list_and_element/1?

:- type list_and_element(T).

/*  Alternative
:- type list_and_element(posint) > list(posint).
:- type list_and_element(posint) > element(posint).
:- type list_and_element(atom)   > list(atom).
:- type list_and_element(atom)   > element(atom).
*/


:- type list_and_element(T)  > list(T).
:- type list_and_element(T)  > element(T).


?- A = [1,2,3,4], ttt(A).        % ok
?- ttt([1,2,[8,9],3]).           % ok
ttt([5,B]) :- B = [3,4].         % ok, B*list(posint)


?- A = [1,2,[8,9],3], ttt(A).    % ok, A*list(list_and_element(posint))
ttt(A) :- A=[5,B], B = [3,4].    % ok     (but not generic)
                              % A*list(list_and_element(posint)),B*list(posint)


:- ttt([1,2,3]).                             % ok
:- ttt([[2,3],[4,5]]).                       % ok
:- ttt([[2,[3,4]]]).                         % ok

:- A = [[1],2,[1,2,3]], ttt(A).              % A*list(list_and_element(posint))
:- ttt([[1],2,[1,2,3]]).                     % ok

:- ttt([[dies],ist,[der,atom,test]]).        % ok
:- A = [[dies],ist,[der,atom,test]], ttt(A). % A*list(list_and_element(atom))

