module Data.Homeomorphic.Check where import qualified Data.Homeomorphic.Simple as H1 import qualified Data.Homeomorphic.SimpleParallel as H2 import qualified Data.Homeomorphic.Hash1 as H3 import qualified Data.Homeomorphic.Hash2 as H4 import qualified Data.Homeomorphic.Memo as H5 import qualified Data.Homeomorphic.MemoCache as H6 import Data.Homeomorphic.Internal import Data.Maybe import Data.List(sort,(\\)) data Homeomorphic k v = Homeomorphic (H1.Homeomorphic k v) (H2.Homeomorphic k v) (H3.Homeomorphic k v) (H4.Homeomorphic k v) (H5.Homeomorphic k v) (H6.Homeomorphic k v) empty :: Homeomorphic k v empty = Homeomorphic H1.empty H2.empty H3.empty H4.empty H5.empty H6.empty insert :: Ord k => Shell k -> v -> Homeomorphic k v -> Homeomorphic k v insert k v (Homeomorphic h1 h2 h3 h4 h5 h6) = Homeomorphic (H1.insert k v h1) (H2.insert k v h2) (H3.insert k v h3) (H4.insert k v h4) (H5.insert k v h5) (H6.insert k v h6) -- additional Eq v constraint required to check the answers -- additional Show constraints required to give a meainingful error message find :: (Ord k, Eq v, Show v, Show k) => Shell k -> Homeomorphic k v -> [v] find k (Homeomorphic h1 h2 h3 h4 h5 h6) = check [H1.find k h1 >< H1.findOne k h1 ,H2.find k h2 >< H2.findOne k h2 ,H3.find k h3 >< H3.findOne k h3 ,H4.find k h4 >< H4.findOne k h4 ,H5.find k h5 >< H5.findOne k h5 ,H6.find k h6 >< H6.findOne k h6 ] where [] >< Nothing = [] xs >< Just x | x `elem` xs = xs _ >< _ = error "Find, inconsistent between find and findOne" check (x:xs) | all (setEq x) xs = x check _ = error "Find, inconsistent between different ones" setEq x y = null (x \\ y) && null (y \\ x) -- find does lots of checking, so can just use that findOne :: (Ord k, Eq v, Show v, Show k) => Shell k -> Homeomorphic k v -> Maybe v findOne k = listToMaybe . find k