/* searchtree.q: An example showing the use of algebraic data types with inheritance. */ /* We first define a generic search tree type (we call this an "abstract" type since it doesn't have any constructors of its own). This type is used as the supertype for two concrete subtypes BinTree and AVLTree below. NB: The `public' keyword causes the type to be exported so that it can be used in other modules which import this script. */ public type Tree; /* Interface operations to be provided by all subtypes of the Tree type: insert/delete elements, compute the list of members (in ascending order), test membership. In this example we allow multiple instances of the same element in a tree. This means that the resulting trees will represent multisets. */ public insert T X, delete T X, members T, member T X; /* Generic tree operations implemented in terms of the interface functions: size, union, difference, intersection, subset comparison. */ #T:Tree = #members T; T1:Tree + T2:Tree = foldl insert T1 (members T2); T1:Tree - T2:Tree = foldl delete T1 (members T2); T1:Tree * T2:Tree = T1 - (T1 - T2); T1:Tree <= T2:Tree = all (member T2) (members T1); T1:Tree >= T2:Tree = all (member T1) (members T2); T1:Tree < T2:Tree = (T1<=T2) and then not (T2<=T1); T1:Tree > T2:Tree = (T1>=T2) and then not (T2>=T1); (T1:Tree = T2:Tree) = (T1<=T2) and then (T2<=T1); T1:Tree <> T2:Tree = not (T1=T2); /* The binary tree and AVL tree subtypes, along with corresponding virtual constructor functions which create a tree from a list of its members. The real constructors are private so that they cannot be (ab)used outside this module. */ public type BinTree : Tree = virtual bintree Xs | private const nil, bin X T1 T2; public type AVLTree : Tree = virtual avltree Xs | private const anil, abin H X T1 T2; /* Define the corresponding views in terms of the virtual constructors. */ view T:BinTree = '(bintree ~(members T)); view T:AVLTree = '(avltree ~(members T)); /* Note that the above definitions of the generic tree operations apply to _all_ subtypes of Tree (provided that they implement the required interface operations). Examples: */ def T1 = avltree [17,5,26,5], T2 = bintree [8,17], S = T1+T2, T = T1-T2; /* Also note that the views for BinTree and AVLTree objects we defined above let us use the virtual constructors in pattern-matching definitions just as if they were real constructors. The virtual representations of these objects will be constructed on the fly, as they are required during pattern matching. Since the virtual constructors are public, this will even work outside this module. Examples: */ def avltree Xs = S, avltree Ys = T; mymembers (bintree Xs) = Xs; mymembers (avltree Xs) = Xs; /* Implementation of the BinTree operations. */ bintree Xs = foldl insert nil Xs; members nil = []; members (bin X T1 T2) = members T1 ++ [X] ++ members T2; member nil Y = false; member (bin X T1 T2) Y = member T1 Y if X>Y; = member T2 Y if XY; = bin X T1 (insert T2 Y) otherwise; delete nil Y = nil; delete (bin X T1 T2) Y = bin X (delete T1 Y) T2 if X>Y; = bin X T1 (delete T2 Y) if XY; = member T2 Y if XY; = rebal (mknode X T1 (insert T2 Y)) otherwise; delete anil Y = anil; delete (abin H X T1 T2) Y = rebal (mknode X (delete T1 Y) T2) if X>Y; = rebal (mknode X T1 (delete T2 Y)) if X