module Boolean.TrueSet(
    TrueSet,
    fromList,
    member,
    empty,
    full,
    single,
    insert,
    delete,
    unions,
    union,
    intersection,
    intersections,
    difference,
    (\\)
    ) where

import Prelude hiding(not,(&&),(||),and,or)
import qualified Data.Set as Set
import Boolean.Algebra

infixl 9 \\


data Ord a => TrueSet a = EverythingBut (Set a) | NothingBut (Set a)

instance BooleanAlgebra (TrueSet a) where
    not (EverythingBut s) = NothingBut s
    not (NothingBut s) = EverythingBut s
    and = intersections
    or = unions
    true = EverythingBut empty
    false = NothingBut empty

    EverythingBut x && EverythingBut y = EverythingBut (x `Set.union` y)
    NothingBut x && NothingBut y = NothingBut (x `Set.intersection` y)
    EverythingBut x && NothingBut y = NothingBut (y Set.\\ x)
    NothingBut x && EverythingBut y = NothingBut (x Set.\\ y)
    EverythingBut x || EverythingBut y = EverythingBut (x `Set.intersection` y)
    NothingBut x || NothingBut y = NothingBut (x `Set.union` y)
    EverythingBut x || NothingBut y = EverythingBut (x Set.\\ y)
    NothingBut x || EverythingBut y = EverithingBut (y Set.\\ x)


fromList = NothingBut . Set.fromList
member x (NothingBut s) = Set.member x s
member x (EverythingBut s) = not (Set.member x s)

empty = false
full = true
single = NothingBut . Set.single
insert x (NothingBut s) = NothingBut (Set.insert x s)
insert x (EverythingBut s) = EverythingBut (Set.delete x s)
delete x (NothingBut s) = NothingBut (Set.delete x s)
delete x (EverythingBut s) = EverythingBut (Set.insert x s)

unions xs = foldlStrict (||) false xs
intersections xs = foldlStrict (&&) true xs

foldlStrict f z xs
  = case xs of
      []     -> z
      (x:xx) -> let z' = f z x in seq z' (foldlStrict f z' xx)

union x y = x || y
intersection x y = x && y
difference x y = x && not y
m1 \\ m2 = difference m1 m2
