/*
 *    list utility 
 */

// <append #out #in1 #in2>
<append #X () #X >;
<append (#A : #Z) (#A : #X)  #Y>
	<append #Z #X #Y >;

?<append #out (a b c) (d e f)>;

// <reverse #out #in>
<reverse () ()>;
<reverse #r (#x: #l) >	
	<reverse #r1 #l >
	<append #r #r1 (#x) >;

?<reverse #out ( a b c)>;
?<reverse  ( a b c) #out>;

// <member #mem #list>
<member #x (#x : #rest)>;
<member #x (#y : #rest)>
 	<member #x #rest>;

?<member a (a b c)>;
?<member d (a b c)>;


// <last #out #list>
<last #x (#x)>;
<last #x (_:#list)>
	<last #x #list>;

?<last #out (a b (c d))>;

// <flatten #out #in>
<flatten () ()>;
<flatten #list (#x:#l)>
	::sys <isList #x>
	<flatten #list1 #x>
	<flatten #list2 #l>
	<append #list #list1 #list2>;
<flatten #list (#x:#l) >
	<flatten #list2 #l>
	<append #list (#x) #list2>;

?<flatten #out (a (b (c d) e (f (g)) h i) j k)>;



// <difference #out #in1 #in2>
<difference () () _ >;
<difference #diff (#x:#set1) #set2 >
	<member #x #set2> 
	<difference #diff #set1 #set2>;
<difference (#x : #diff) (#x:#set1) #set2>
	<difference #diff #set1 #set2>;

?<difference #out (a b c d e f g h i j ) (1 2 3 b c l i m j a)>;


<equal_sets #set1 #set2>
	<difference () #set1 #set2>
	<difference () #set2 #set1>;

//?<equal_sets (a b c d e f g h i j ) (1 2 3 b c l i m j a)>;
?<equal_sets (a b c d e f g h i j ) (d e f a b c g h i j )>;


// <intersect #out #in1 #in2>
<intersect () () _ >;
<intersect (#x:#int) (#x:#set1) #set2>
	<member #x #set2>
	<intersect #int #set1 #set2>;
<intersect #int (_:#set1) #set2>
	<intersect #int #set1 #set2>;

?<intersect #out (i j k l m) (n m l k)>;

// <union #out #in1 #in2>
<union #out () #out>;
<union #out (#x : #in1) #in2>
	<member #x #in2>
	<union #out #in1 #in2>
	;
<union (#x : #out) (#x : #in1) #in2>
	<union #out #in1 #in2>
	;
?<union #x (c b a) (a d c e f)>;

// <subset #subset #set>
<subset () #set>;
<subset (#x : #subset) #set>
	<member #x #set>
	<subset #subset #set>;

?<subset (a b c) (f g b h d c i a)>;

// <join #out #in1 #in2>
<join () () ()>;
<join (#x #y : #out) (#x : #in1) (#y : #in2)>
	<join #out #in1 #in2>;

?<join #x (a b c) (1 2 3)>;

// <occures #n #e #list>

<occurs 0 _ ()>;
<occurs #n #e (#e : #list)>
	<occurs #m #e #list>
	<let #n = #m+1>
	;
<occurs #n #e (_ : #list) >
	<occurs #n #e #list>
	;

? <occurs #n e (a b c d e f e g h e)>;

