module Data.Set.Range.Combine
( difference
, intersect
, union
) where
import Data.Set.Range.Overlap
import Data.Set.Range.Types
merge :: (Eq a, Enum a)
=> RangeSet a
-> RangeSet a
merge [] = []
merge [xs] = [xs]
merge ((a,b) : (c,d) : xs)
| b == c = merge ((a,d) : xs)
| succ b == c = merge ((a,d) : xs)
| otherwise = (a,b) : merge ((c,d) : xs)
difference :: (Ord a, Enum a)
=> RangeSet a
-> RangeSet a
-> RangeSet a
difference xs [] = xs
difference [] _ = []
difference ((a,b) : xs) ((c,d) : ys) = go $ overlap (a,b) (c,d)
where
go Equal = difference xs ys
go FstSmaller = (a,b) : difference xs ((c,d) : ys)
go FstInside = difference xs ((c,d) : ys)
go FstOverlap = (a,pred c) : difference xs ((succ b,d) : ys)
go SndSmaller = difference ((a,b) : xs) ys
go SndInside
| a == c = difference ((succ d,b) : xs) ys
| otherwise = (a,pred c) : difference ((succ d,b) : xs) ys
go SndOverlap = difference ((succ d,b) : xs) ys
intersect :: (Ord a, Enum a)
=> RangeSet a
-> RangeSet a
-> RangeSet a
intersect _ [] = []
intersect [] _ = []
intersect ((a,b) : xs) ((c,d) : ys) = merge $ go $ overlap (a,b) (c,d)
where
go Equal = (a,b) : intersect xs ys
go FstSmaller = intersect xs ((c,d) : ys)
go FstInside = (a,b) : intersect xs ((b,d) : ys)
go FstOverlap = (c,b) : intersect xs ((b,d) : ys)
go SndInside = (c,d) : intersect ((d,b) : xs) ys
go SndSmaller = intersect ((a,b) : xs) ys
go SndOverlap = (a,d) : intersect ((d,b) : xs) ys
union :: (Ord a, Enum a)
=> RangeSet a
-> RangeSet a
-> RangeSet a
union xs [] = xs
union [] ys = ys
union ((a,b) : xs) ((c,d) : ys) = merge $ go $ overlap (a,b) (c,d)
where
go Equal = (a,b) : union xs ys
go FstSmaller = (a,b) : union xs ((c,d) : ys)
go FstInside = union xs ((c,d) : ys)
go FstOverlap = (a,b) : union xs ((b,d) : ys)
go SndSmaller = (c,d) : union ((a,b) : xs) ys
go SndInside = union ((a,b) : xs) ys
go SndOverlap = (c,d) : union ((d,b) : xs) ys