
Stijn De Saeger wrote:
Now, for unions I tried the following: to take the union of two BasicSets, just append them and contract the result. contracting meaning: merge overlapping intervals.
contract :: Range -> Range -> BasicSet contract (x1,y1) (x2,y2) | x2 <= y1 = if x2 >= x1 then [(x1, (max y1 y2))] else if y2 >= x1 then [(x2, (max y1 y2))] else [(x2,y2), (x1,y1)] | x1 <= y2 = if x1 >= x2 then [(x2, (max y1 y2))] else if y1 >= x2 then [(x1, (max y1 y2))] else [(x1,y1), (x2,y2)] | x1 <= x2 = [(x1,y1), (x2, y2)]
Now generalizing this from Ranges to BasicSets is where i got stuck. In my limited grasp of haskell and FP, this contractSet function below is just crying for the use of a fold operation, but i can't for the life of me see how to do it.
contractSet :: BasicSet -> BasicSet contractSet [] = [] contractSet (x:xs) = foldl contract x xs -- this doesn't work, though...
The problem is you need to compare each range in x with each range in y... unless they are both ordered smallest real to largest, in which case you need to use a 'merge-sort' technique, taking the range with the lowest starting value from the head of either x or y, unless the ranges at the top of x and y overlap in which case you merge the ranges. This is not naturally represented by a fold. contractSet :: BasicSet -> BasticSet -> BasicSet contractSet x@(x0@(sx,ex):xs) y@(y0:(sy,ey):ys) | ex < sy = x0:contractSet xs y | sy < sx = y0:contractSet x ys | otherwise = contract x0 y0:contractSet xs ys Keean.