/*
 *    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)>;

// <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)>;

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

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



// <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)>;

