% File 'meta_map_filter.pl'
%----
:- ensure_loaded(typeops_meta).

% meta-programming
% map/3 predicate
% filter/3 predicate

% 
%+++++++++++++++++++++++++++++ type definitions +++++++++++++++++++++++ 

:- import_type(prolog_types).

:- suptype numexpr2  >  numexpr.
:- type    numexpr2 --> numexpr2 mod numexpr2.

% 
%+++++++++++++++++++++++++++++ predicates  +++++++++++++++++++++++ 

:- import_pred(prolog_meta,fcall/3).
:- import_pred(prolog_meta,fcall/2).

:- import_pred(prolog_meta,';'/2).
:- import_pred(prolog_meta,var/1).
:- import_pred(prolog_meta,'->'/2).
:- import_pred(prolog_meta,'='/2).
:- import_pred(prolog_meta,!/0).

:- pred map(meta((trmName(@T1,@T2) of mpred)), list(T1), list(T2)).
map(_F,[],[]).
map(F, [A0|As0], [A|As]) :-
	fcall(F,A0,A),
	map(F,As0,As).

:- pred filter(meta((trmName(@T) of mpred)), list(T), list(T)).
filter(_P, [], []).
filter(P, [A0|As0], As) :-
	(fcall(P,A0) ->
		As = [A0|As1]
	;
		As = As1
	),
	filter(P, As0, As1).

:- pred inc(int, int).
inc(X,Y) :- var(X), !, X is Y - 1.
inc(X,Y) :- Y is X + 1.


:- pred even(int).
even(X) :- 0 is X mod 2.

:- pred num is numexpr2.

% 
%+++++++++++++++++++++++++++++ tests  ++++++++++++++++++++++++++ 

:- map(inc, [1,2,3], X).
:- map(inc, X, [2,3,4]).

:- filter(even, [1,2,4,3,5,3,6,4], X).


:- map(even, X, [2,3,4]).                  % ill-typed
:- filter(inc, [1,2,4,3,5,3,6,4], X).      % ill-typed

