% ================================================================= :- pred constr(bool). :- mode constr(in). :- ignore constr/1. % ==================================================== % Program. :- pred perm(list(int),list(int)). :- mode perm(in,in). % in,in: perm is not functional perm([],[]). perm([X|Xs],[H|Perm]):- % a permutation cons(X,Xs,XXs), delete(H,XXs,Rest), perm(Rest,Perm). :- pred delete(int,list(int),list(int)). :- mode delete(in,in,in). % delete is not total delete(X,[Y|T],T) :- constr(X=Y). % Taking X away from [Y|T]. Deleting exactly one copy of X. delete(X,[Y|T],[Y|TD]) :- % The list need not be ordered. Element X need not be the minimum. constr(~(X=Y)), % delete(X,L,LD) succeeds **IFF** X is a member of L. delete(X,TD,T). % error: delete(X,TD,T) ---> delete(X,T,TD). :- pred cons(int,list(int),list(int)). :- mode cons(in,in,out). cons(H,T,[H|T]). % ==================================================== % catamorphisms :- pred listcount(int,list(int),int). :- mode listcount(in,in,out). :- cata listcount/3-2. listcount(X,[],Res) :- constr( (Res=0) ). listcount(X,[Y|Ys],Res) :- constr( Res=ite(X=Y,ResT+1,ResT) ), listcount(X,Ys,ResT). % ==================================================== % verification. % Property: :- pred ff1. ff1 :- constr( ~(LS=LPS)), listcount(X,L,LS), listcount(X,LP,LPS), perm(L,LP). %% contracts (postcondition: true) % %:- spec delete(H,L,LD) ==> listcount(X,L,SL), listcount(X,LD,SLD). % %:- spec cons(H,T,HT) ==> listcount(X,T,ST), listcount(X,HT,SHT). % ==================================================== :- query ff1/0. % ==================================================== % Catamorphic abstraction :- cata_abs list(int) ==> listcount(X,L,SL). % ======================================================s